'Static data model implementation in Worklet

Change-Id: Ic5eeb26eaea547523befd509f9f48281cb4c2031
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/DefaultWorkletDescription.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/DefaultWorkletDescription.java
new file mode 100644
index 0000000..82bb3f8
--- /dev/null
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/DefaultWorkletDescription.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.workflow.api;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.base.MoreObjects;
+import org.slf4j.Logger;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Class for default worklet description.
+ */
+public final class DefaultWorkletDescription implements WorkletDescription {
+
+    protected static final Logger log = getLogger(DefaultWorkletDescription.class);
+
+    /**
+     * worklet Name.
+     */
+    private String tag;
+
+    /**
+     * worklet data model.
+     */
+    private JsonDataModelTree data;
+
+    /**
+     * Constructor of worklet description.
+     *
+     * @param builder worklet description builder
+     */
+    public DefaultWorkletDescription(DefaultWorkletDescription.Builder builder) {
+        this.tag = builder.tag;
+        this.data = builder.data;
+    }
+
+    public DefaultWorkletDescription(String tag) {
+        this.tag = tag;
+    }
+
+    @Override
+    public String tag() {
+        return this.tag;
+    }
+
+    @Override
+    public JsonDataModelTree data() {
+        return this.data;
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(getClass())
+                .add("tag", tag())
+                .add("data", data())
+                .toString();
+    }
+
+    /**
+     * Gets builder instance.
+     *
+     * @return builder instance
+     */
+    public static DefaultWorkletDescription.Builder builder() {
+        return new DefaultWorkletDescription.Builder();
+    }
+
+    /**
+     * Builder for worklet description.
+     */
+    public static class Builder {
+
+        /**
+         * worklet name.
+         */
+        private String tag;
+
+        /**
+         * static data model tree.
+         */
+        JsonDataModelTree data = new JsonDataModelTree();
+
+        /**
+         * Sets worklet name.
+         *
+         * @param tag worklet name
+         * @return builder
+         */
+        public DefaultWorkletDescription.Builder name(String tag) {
+            this.tag = tag;
+            return this;
+        }
+
+
+        public DefaultWorkletDescription.Builder staticDataModel(String path, String value) throws WorkflowException {
+
+            data.setAt(path, value);
+
+            return this;
+        }
+
+        public DefaultWorkletDescription.Builder staticDataModel(String path, Integer value) throws WorkflowException {
+
+            data.setAt(path, value);
+
+            return this;
+        }
+
+        public DefaultWorkletDescription.Builder staticDataModel(String path, Boolean value) throws WorkflowException {
+
+            data.setAt(path, value);
+
+            return this;
+        }
+
+        public DefaultWorkletDescription.Builder staticDataModel(String path, JsonNode value) throws WorkflowException {
+
+            data.setAt(path, value);
+
+            return this;
+        }
+
+        public DefaultWorkletDescription.Builder staticDataModel(String path, ArrayNode value)
+                throws WorkflowException {
+
+            data.setAt(path, value);
+
+            return this;
+        }
+
+        public DefaultWorkletDescription.Builder staticDataModel(String path, ObjectNode value)
+                throws WorkflowException {
+
+            data.setAt(path, value);
+
+            return this;
+        }
+
+
+        /**
+         * Builds worklet description from builder.
+         *
+         * @return instance of worklet description
+         * @throws WorkflowException workflow exception
+         */
+        public DefaultWorkletDescription build() {
+
+            return new DefaultWorkletDescription(this);
+        }
+
+
+    }
+}
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/ImmutableListWorkflow.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/ImmutableListWorkflow.java
index 3e54c94..f4d9470 100644
--- a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/ImmutableListWorkflow.java
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/ImmutableListWorkflow.java
@@ -27,6 +27,7 @@
 import java.net.URI;
 import java.util.List;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 
 import static org.onosproject.workflow.api.CheckCondition.check;
@@ -42,9 +43,9 @@
     private String initWorkletType;
 
     /**
-     * List of worklet.
+     * List of worklet  description.
      */
-    private List<String> workletTypeList;
+    private List<WorkletDescription> workletDescList;
 
     /**
      * Set of workflow attributes.
@@ -52,6 +53,7 @@
     private Set<WorkflowAttribute> attributes;
 
     private static JsonDataModelInjector dataModelInjector = new JsonDataModelInjector();
+    private static StaticDataModelInjector staticDataModelInjector = new StaticDataModelInjector();
 
     /**
      * Constructor of ImmutableListWorkflow.
@@ -61,7 +63,7 @@
     private ImmutableListWorkflow(Builder builder) {
         super(builder.id);
         this.initWorkletType = builder.initWorkletType;
-        workletTypeList = ImmutableList.copyOf(builder.workletTypeList);
+        workletDescList = ImmutableList.copyOf(builder.workletDescList);
         attributes = ImmutableSet.copyOf(builder.attributes);
     }
 
@@ -84,12 +86,11 @@
 
         ProgramCounter pc = current.clone();
 
-        for (int i = current.workletIndex(); i < workletTypeList.size(); pc = increased(pc), i++) {
+        for (int i = current.workletIndex(); i < workletDescList.size(); pc = increased(pc), i++) {
 
             if (cnt++ > Worklet.MAX_WORKS) {
                 throw new WorkflowException("Maximum worklet execution exceeded");
             }
-
             if (pc.isCompleted()) {
                 return pc;
             }
@@ -119,6 +120,12 @@
             } else {
                 // isNext is read only. It does not perform 'inhale'.
                 dataModelInjector.inject(worklet, context);
+                WorkletDescription workletDesc = getWorkletDesc(pc);
+                if (Objects.nonNull(workletDesc)) {
+                    if (!(workletDesc.tag().equals("INIT") || workletDesc.tag().equals("COMPLETED"))) {
+                        staticDataModelInjector.inject(worklet, workletDesc);
+                    }
+                }
                 if (worklet.isNext(context)) {
                     return pc;
                 }
@@ -132,18 +139,18 @@
     public ProgramCounter increased(ProgramCounter pc) throws WorkflowException {
 
         int increaedIndex = pc.workletIndex() + 1;
-        if (increaedIndex >= workletTypeList.size()) {
+        if (increaedIndex >= workletDescList.size()) {
             throw new WorkflowException("Out of bound in program counter(" + pc + ")");
         }
 
-        String workletType = workletTypeList.get(increaedIndex);
-        return ProgramCounter.valueOf(workletType, increaedIndex);
+        WorkletDescription workletDesc = workletDescList.get(increaedIndex);
+        return ProgramCounter.valueOf(workletDesc.tag(), increaedIndex);
     }
 
     @Override
     public Worklet getWorkletInstance(ProgramCounter pc) throws WorkflowException {
 
-        return getWorkletInstance(workletTypeList.get(pc.workletIndex()));
+        return getWorkletInstance(workletDescList.get(pc.workletIndex()).tag());
     }
 
     @Override
@@ -191,10 +198,21 @@
     }
 
     @Override
-    public List<String> getWorkletTypeList() {
-        return ImmutableList.copyOf(workletTypeList);
+    public List<WorkletDescription> getWorkletDescList() {
+        return ImmutableList.copyOf(workletDescList);
     }
 
+    @Override
+    public WorkletDescription getWorkletDesc(ProgramCounter pc) {
+        Optional<WorkletDescription> workletDescription = workletDescList.stream().filter(a -> Objects.equals(a.tag(),
+                workletDescList.get(pc.workletIndex()).tag())).findAny();
+        if (workletDescription.isPresent()) {
+            return workletDescription.get();
+        }
+        return null;
+    }
+
+
     /**
      * Gets index of class in worklet type list.
      *
@@ -202,8 +220,8 @@
      * @return index of class in worklet type list
      */
     private int getClassIndex(Class aClass) {
-        for (int i = 0; i < workletTypeList.size(); i++) {
-            if (Objects.equals(aClass.getName(), workletTypeList.get(i))) {
+        for (int i = 0; i < workletDescList.size(); i++) {
+            if (Objects.equals(aClass.getName(), workletDescList.get(i))) {
                 return i;
             }
         }
@@ -247,7 +265,7 @@
         }
         return Objects.equals(this.id(), ((ImmutableListWorkflow) obj).id())
                 && Objects.equals(this.initWorkletType, ((ImmutableListWorkflow) obj).initWorkletType)
-                && Objects.equals(this.workletTypeList, ((ImmutableListWorkflow) obj).workletTypeList)
+                && Objects.equals(this.workletDescList, ((ImmutableListWorkflow) obj).workletDescList)
                 && Objects.equals(this.attributes, ((ImmutableListWorkflow) obj).attributes);
     }
 
@@ -256,7 +274,7 @@
         return MoreObjects.toStringHelper(getClass())
                 .add("id", id())
                 .add("initWorklet", initWorkletType)
-                .add("workList", workletTypeList)
+                .add("workList", workletDescList)
                 .add("attributes", attributes)
                 .toString();
     }
@@ -277,7 +295,7 @@
 
         private URI id;
         private String initWorkletType;
-        private final List<String> workletTypeList = Lists.newArrayList();
+        private final List<WorkletDescription> workletDescList = Lists.newArrayList();
         private final Set<WorkflowAttribute> attributes = Sets.newHashSet();
 
         /**
@@ -288,7 +306,7 @@
          */
         public Builder id(URI uri) {
             this.id = uri;
-            workletTypeList.add(Worklet.Common.INIT.tag());
+            workletDescList.add(new DefaultWorkletDescription(Worklet.Common.INIT.tag()));
             return this;
         }
 
@@ -310,7 +328,7 @@
          * @return builder
          */
         public Builder chain(String workletClassName) {
-            workletTypeList.add(workletClassName);
+            workletDescList.add(new DefaultWorkletDescription(workletClassName));
             return this;
         }
 
@@ -331,8 +349,13 @@
          * @return instance of ImmutableListWorkflow
          */
         public ImmutableListWorkflow build() {
-            workletTypeList.add(Worklet.Common.COMPLETED.tag());
+            workletDescList.add(new DefaultWorkletDescription(Worklet.Common.COMPLETED.tag()));
             return new ImmutableListWorkflow(this);
         }
+
+        public Builder chain(DefaultWorkletDescription workletDesc) {
+            workletDescList.add(workletDesc);
+            return this;
+        }
     }
 }
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/JsonDataModelTree.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/JsonDataModelTree.java
index 7ee1be7..aec19ae 100644
--- a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/JsonDataModelTree.java
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/JsonDataModelTree.java
@@ -56,6 +56,7 @@
 
     /**
      * Constructor of JsonDataModelTree.
+     *
      * @param root root node of json data model tree
      */
     public JsonDataModelTree(JsonNode root) {
@@ -169,7 +170,8 @@
 
     /**
      * Allocates json data model tree on json pointer path with specific leaf type.
-     * @param ptr json pointer to allocate
+     *
+     * @param ptr      json pointer to allocate
      * @param leaftype type of leaf node
      * @return json data model tree
      * @throws WorkflowException workflow exception
@@ -194,6 +196,7 @@
 
     /**
      * Gets root json node.
+     *
      * @return root json node
      * @throws WorkflowException workflow exception
      */
@@ -203,6 +206,7 @@
 
     /**
      * Gets root json node as ObjectNode (MAP type).
+     *
      * @return root json node as ObjectNode
      * @throws WorkflowException workflow exception
      */
@@ -212,6 +216,7 @@
 
     /**
      * Gets root json node as ArrayNode (Array type).
+     *
      * @return root json node as ArrayNode
      * @throws WorkflowException workflow exception
      */
@@ -221,6 +226,7 @@
 
     /**
      * Gets json node on specific path.
+     *
      * @param path path of json node
      * @return json node on specific path
      * @throws WorkflowException workflow exception
@@ -232,6 +238,7 @@
 
     /**
      * Gets json node on specific json pointer.
+     *
      * @param ptr json pointer
      * @return json node on specific json pointer.
      * @throws WorkflowException workflow exception
@@ -246,6 +253,7 @@
 
     /**
      * Gets json node on specific path as ObjectNode.
+     *
      * @param path path of json node
      * @return ObjectNode type json node on specific path
      * @throws WorkflowException workflow exception
@@ -257,6 +265,7 @@
 
     /**
      * Gets json node on specific json pointer as ObjectNode.
+     *
      * @param ptr json pointer
      * @return ObjectNode type json node on specific json pointer.
      * @throws WorkflowException workflow exception
@@ -277,6 +286,7 @@
 
     /**
      * Gets json node on specific path as ArrayNode.
+     *
      * @param path path of json node
      * @return ArrayNode type json node on specific path
      * @throws WorkflowException workflow exception
@@ -288,6 +298,7 @@
 
     /**
      * Gets json node on specific json pointer as ArrayNode.
+     *
      * @param ptr json pointer
      * @return ArrayNode type json node on specific json pointer.
      * @throws WorkflowException workflow exception
@@ -308,6 +319,7 @@
 
     /**
      * Gets text node on specific path.
+     *
      * @param path path of json node
      * @return text on specific path
      * @throws WorkflowException workflow exception
@@ -319,6 +331,7 @@
 
     /**
      * Gets text on specific json pointer.
+     *
      * @param ptr json pointer
      * @return text on specific json pointer
      * @throws WorkflowException workflow exception
@@ -339,6 +352,7 @@
 
     /**
      * Gets integer node on specific path.
+     *
      * @param path path of json node
      * @return integer on specific path
      * @throws WorkflowException workflow exception
@@ -350,6 +364,7 @@
 
     /**
      * Gets integer on specific json pointer.
+     *
      * @param ptr json pointer
      * @return integer on specific json pointer
      * @throws WorkflowException workflow exception
@@ -370,6 +385,7 @@
 
     /**
      * Gets boolean on specific path.
+     *
      * @param path path of json node
      * @return boolean on specific path
      * @throws WorkflowException workflow exception
@@ -381,6 +397,7 @@
 
     /**
      * Gets boolean on specific json pointer.
+     *
      * @param ptr json pointer
      * @return boolean on specific json pointer
      * @throws WorkflowException workflow exception
@@ -401,6 +418,7 @@
 
     /**
      * Sets text on specific json path.
+     *
      * @param path json path
      * @param text text to set
      * @throws WorkflowException workflow exception
@@ -412,18 +430,21 @@
 
     /**
      * Sets text on the specific json pointer.
-     * @param ptr json pointer
+     *
+     * @param ptr  json pointer
      * @param text text to set
      * @throws WorkflowException workflow exception
      */
     public void setAt(JsonPointer ptr, String text) throws WorkflowException {
         TextNode textNode = TextNode.valueOf(text);
+
         attach(ptr, textNode);
     }
 
     /**
      * Sets boolean on specific json path.
-     * @param path json path
+     *
+     * @param path   json path
      * @param isTrue boolean to set
      * @throws WorkflowException workflow exception
      */
@@ -433,8 +454,83 @@
     }
 
     /**
+     * Sets text on the specific json pointer.
+     *
+     * @param ptr      json pointer
+     * @param jsonNode jsonNode to set
+     * @throws WorkflowException workflow exception
+     */
+    public void setAt(JsonPointer ptr, JsonNode jsonNode) throws WorkflowException {
+        JsonNode node = jsonNode;
+        attach(ptr, node);
+    }
+
+    /**
+     * Sets boolean on specific json path.
+     *
+     * @param path     json path
+     * @param jsonNode jsonNode to set
+     * @throws WorkflowException workflow exception
+     */
+    public void setAt(String path, JsonNode jsonNode) throws WorkflowException {
+        JsonPointer ptr = JsonPointer.compile(path);
+        setAt(ptr, jsonNode);
+    }
+
+
+    /**
+     * Sets text on the specific json pointer.
+     *
+     * @param ptr       json pointer
+     * @param arrayNode arrayNode to set
+     * @throws WorkflowException workflow exception
+     */
+    public void setAt(JsonPointer ptr, ArrayNode arrayNode) throws WorkflowException {
+        ArrayNode node = arrayNode;
+        attach(ptr, node);
+    }
+
+    /**
+     * Sets boolean on specific json path.
+     *
+     * @param path      json path
+     * @param arrayNode arrayNode to set
+     * @throws WorkflowException workflow exception
+     */
+    public void setAt(String path, ArrayNode arrayNode) throws WorkflowException {
+        JsonPointer ptr = JsonPointer.compile(path);
+        setAt(ptr, arrayNode);
+    }
+
+    /**
+     * Sets text on the specific json pointer.
+     *
+     * @param ptr        json pointer
+     * @param objectNode objectNode to set
+     * @throws WorkflowException workflow exception
+     */
+    public void setAt(JsonPointer ptr, ObjectNode objectNode) throws WorkflowException {
+        ObjectNode node = objectNode;
+        attach(ptr, node);
+    }
+
+    /**
+     * Sets boolean on specific json path.
+     *
+     * @param path       json path
+     * @param objectNode objectNode to set
+     * @throws WorkflowException workflow exception
+     */
+    public void setAt(String path, ObjectNode objectNode) throws WorkflowException {
+        JsonPointer ptr = JsonPointer.compile(path);
+        setAt(ptr, objectNode);
+    }
+
+
+    /**
      * Sets boolean on the specific json pointer.
-     * @param ptr json pointer
+     *
+     * @param ptr    json pointer
      * @param isTrue boolean to set
      * @throws WorkflowException workflow exception
      */
@@ -445,7 +541,8 @@
 
     /**
      * Sets integer on specific json path.
-     * @param path json path
+     *
+     * @param path   json path
      * @param number number to set
      * @throws WorkflowException workflow exception
      */
@@ -456,7 +553,8 @@
 
     /**
      * Sets integer on the specific json pointer.
-     * @param ptr json pointer
+     *
+     * @param ptr    json pointer
      * @param number number to set
      * @throws WorkflowException workflow exception
      */
@@ -467,8 +565,9 @@
 
     /**
      * Allocates json data model tree on json pointer path with specific leaf type.
-     * @param node current json node in the json tree path
-     * @param ptr json pointer
+     *
+     * @param node     current json node in the json tree path
+     * @param ptr      json pointer
      * @param leaftype leaf type to be allocated
      * @return allocated json node
      * @throws WorkflowException workflow exception
@@ -510,6 +609,7 @@
 
     /**
      * Creating empty json node.
+     *
      * @param type json node type to create
      * @return created json node
      * @throws WorkflowException workflow exception
@@ -528,6 +628,7 @@
 
     /**
      * Gets the pretty json formatted string of this json data model tree.
+     *
      * @return pretty json formatted string of this json data model tree
      */
     public String formattedRootString() {
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/StaticDataModel.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/StaticDataModel.java
new file mode 100644
index 0000000..91e8382
--- /dev/null
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/StaticDataModel.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.workflow.api;
+
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Target(ElementType.FIELD)
+@Retention(RetentionPolicy.RUNTIME)
+
+/**
+ * Annotation for injecting static data model on work-let execution context.
+ */
+public @interface StaticDataModel {
+
+    /**
+     * Path of data model.
+     *
+     * @return path of data model
+     */
+    String path() default "/";
+
+    /**
+     * Representing whether this data model is optional or not.
+     *
+     * @return optional or not
+     */
+    boolean optional() default false;
+}
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/StaticDataModelInjector.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/StaticDataModelInjector.java
new file mode 100644
index 0000000..92d3664
--- /dev/null
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/StaticDataModelInjector.java
@@ -0,0 +1,317 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.workflow.api;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.util.Map;
+import java.util.List;
+import java.util.Objects;
+import java.util.ArrayList;
+import java.util.HashMap;
+
+public class StaticDataModelInjector {
+
+    private static final Logger log = LoggerFactory.getLogger(StaticDataModelInjector.class);
+
+    /**
+     * Injects data model to work-let.
+     *
+     * @param worklet            work-let to be injected
+     * @param workletDescription worklet description
+     * @throws WorkflowException workflow exception
+     */
+    public void inject(Worklet worklet, WorkletDescription workletDescription) throws WorkflowException {
+
+        handle(worklet, workletDescription, this::injectModel);
+    }
+
+    private void handle(Worklet worklet, WorkletDescription workletDescription, DataModelFieldBehavior func)
+            throws WorkflowException {
+        Class cl = worklet.getClass();
+        List<Field> fields = getInheritedFields(cl);
+        if (Objects.isNull(fields)) {
+            log.error("Invalid fields on {}", cl);
+            return;
+        }
+
+        for (Field field : fields) {
+            Annotation[] annotations = field.getAnnotations();
+            if (Objects.isNull(annotations)) {
+                continue;
+            }
+            for (Annotation annotation : annotations) {
+                if (!(annotation instanceof StaticDataModel)) {
+                    continue;
+                }
+                StaticDataModel model = (StaticDataModel) annotation;
+                func.apply(worklet, workletDescription, field, model);
+            }
+        }
+    }
+
+    private static List<Field> getInheritedFields(Class<?> type) {
+        List<Field> fields = new ArrayList<Field>();
+
+        Class<?> cl = type;
+        while (cl != null && cl != Object.class) {
+            for (Field field : cl.getDeclaredFields()) {
+                if (!field.isSynthetic()) {
+                    fields.add(field);
+                }
+            }
+            cl = cl.getSuperclass();
+        }
+        return fields;
+    }
+
+    /**
+     * Functional interface for json data model annotated field behavior.
+     */
+    @FunctionalInterface
+    public interface DataModelFieldBehavior {
+        void apply(Worklet worklet, WorkletDescription workletDescription, Field field, StaticDataModel model)
+                throws WorkflowException;
+    }
+
+    private static Map<Class, DataModelFieldBehavior> injectTypeMap = new HashMap<>();
+
+    static {
+        injectTypeMap.put(String.class, StaticDataModelInjector::injectText);
+        injectTypeMap.put(Integer.class, StaticDataModelInjector::injectInteger);
+        injectTypeMap.put(Boolean.class, StaticDataModelInjector::injectBoolean);
+        injectTypeMap.put(JsonNode.class, StaticDataModelInjector::injectJsonNode);
+        injectTypeMap.put(ArrayNode.class, StaticDataModelInjector::injectArrayNode);
+        injectTypeMap.put(ObjectNode.class, StaticDataModelInjector::injectObjectNode);
+    }
+
+    /**
+     * Injects data model on the filed of work-let.
+     *
+     * @param worklet            work-let
+     * @param workletDescription worklet description
+     * @param field              the field of work-let
+     * @param model              data model for the field
+     * @throws WorkflowException workflow exception
+     */
+    private void injectModel(Worklet worklet, WorkletDescription workletDescription, Field field, StaticDataModel model)
+            throws WorkflowException {
+
+        DataModelFieldBehavior behavior = injectTypeMap.get(field.getType());
+        if (Objects.isNull(behavior)) {
+            throw new WorkflowException("Not supported type(" + field.getType() + ")");
+        }
+        behavior.apply(worklet, workletDescription, field, model);
+    }
+
+    /**
+     * Injects text data model on the filed of work-let.
+     *
+     * @param worklet            work-let
+     * @param workletDescription worklet description
+     * @param field              the field of work-let
+     * @param model              text data model for the field
+     * @throws WorkflowException workflow exception
+     */
+    private static void injectText(Worklet worklet, WorkletDescription workletDescription, Field field,
+                                   StaticDataModel model) throws WorkflowException {
+
+        String text = ((JsonDataModelTree) workletDescription.data()).textAt(model.path());
+        if (Objects.isNull(text)) {
+            if (model.optional()) {
+                return;
+            }
+            throw new WorkflowException("Invalid array node data model on (" + model.path() + ")");
+        }
+
+
+        if (!(Objects.equals(field.getType(), String.class))) {
+            throw new WorkflowException("Target field (" + field + ") is not String");
+        }
+
+        try {
+            field.setAccessible(true);
+            field.set(worklet, text);
+        } catch (IllegalAccessException e) {
+            throw new WorkflowException(e);
+        }
+    }
+
+    /**
+     * Injects integer data model on the filed of work-let.
+     *
+     * @param worklet            work-let
+     * @param workletDescription worklet description
+     * @param field              the field of work-let
+     * @param model              integer data model for the field
+     * @throws WorkflowException workflow exception
+     */
+    private static void injectInteger(Worklet worklet, WorkletDescription workletDescription, Field field,
+                                      StaticDataModel model) throws WorkflowException {
+
+        Integer number = ((JsonDataModelTree) workletDescription.data()).intAt(model.path());
+        if (Objects.isNull(number)) {
+            if (model.optional()) {
+                return;
+            }
+            throw new WorkflowException("Invalid array node data model on (" + model.path() + ")");
+        }
+        if (!(Objects.equals(field.getType(), Integer.class))) {
+            throw new WorkflowException("Target field (" + field + ") is not Integer");
+        }
+
+        try {
+            field.setAccessible(true);
+            field.set(worklet, number);
+        } catch (IllegalAccessException e) {
+            throw new WorkflowException(e);
+        }
+    }
+
+
+    /**
+     * Injects boolean data model on the filed of work-let.
+     *
+     * @param worklet            work-let
+     * @param workletDescription worklet description
+     * @param field              the field of work-let
+     * @param model              boolean data model for the field
+     * @throws WorkflowException workflow exception
+     */
+    private static void injectBoolean(Worklet worklet, WorkletDescription workletDescription, Field field,
+                                      StaticDataModel model) throws WorkflowException {
+
+        Boolean bool = ((JsonDataModelTree) workletDescription.data()).booleanAt(model.path());
+        if (Objects.isNull(bool)) {
+            if (model.optional()) {
+                return;
+            }
+            throw new WorkflowException("Invalid boolean data model on (" + model.path() + ")");
+        }
+
+        if (!(Objects.equals(field.getType(), Boolean.class))) {
+            throw new WorkflowException("Target field (" + field + ") is not Boolean");
+        }
+
+        try {
+            field.setAccessible(true);
+            field.set(worklet, bool);
+        } catch (IllegalAccessException e) {
+            throw new WorkflowException(e);
+        }
+    }
+
+    /**
+     * Injects json node data model on the filed of work-let.
+     *
+     * @param worklet            work-let
+     * @param workletDescription worklet description
+     * @param field              the field of work-let
+     * @param model              json node data model for the field
+     * @throws WorkflowException workflow exception
+     */
+    private static void injectJsonNode(Worklet worklet, WorkletDescription workletDescription, Field field,
+                                       StaticDataModel model) throws WorkflowException {
+
+        JsonNode jsonNode = ((JsonDataModelTree) workletDescription.data()).nodeAt(model.path());
+        if (Objects.isNull(jsonNode)) {
+            if (model.optional()) {
+                return;
+            }
+            throw new WorkflowException("Invalid json node data model on (" + model.path() + ")");
+        }
+
+        if (!(Objects.equals(field.getType(), JsonNode.class))) {
+            throw new WorkflowException("Target field (" + field + ") is not JsonNode");
+        }
+
+        try {
+            field.setAccessible(true);
+            field.set(worklet, jsonNode);
+        } catch (IllegalAccessException e) {
+            throw new WorkflowException(e);
+        }
+    }
+
+    /**
+     * Injects json array node data model on the filed of work-let.
+     *
+     * @param worklet            work-let
+     * @param workletDescription worklet description
+     * @param field              the field of work-let
+     * @param model              json array node data model for the field
+     * @throws WorkflowException workflow exception
+     */
+    private static void injectArrayNode(Worklet worklet, WorkletDescription workletDescription, Field field,
+                                        StaticDataModel model) throws WorkflowException {
+
+        ArrayNode arrayNode = ((JsonDataModelTree) workletDescription.data()).arrayAt(model.path());
+        if (Objects.isNull(arrayNode)) {
+            if (model.optional()) {
+                return;
+            }
+            throw new WorkflowException("Invalid array node data model on (" + model.path() + ")");
+        }
+
+        if (!(Objects.equals(field.getType(), ArrayNode.class))) {
+            throw new WorkflowException("Target field (" + field + ") is not ArrayNode");
+        }
+
+        try {
+            field.setAccessible(true);
+            field.set(worklet, arrayNode);
+        } catch (IllegalAccessException e) {
+            throw new WorkflowException(e);
+        }
+    }
+
+    /**
+     * Injects json object node data model on the filed of work-let.
+     *
+     * @param worklet            work-let
+     * @param workletDescription worklet description
+     * @param field              the field of work-let
+     * @param model              json object node data model for the field
+     * @throws WorkflowException workflow exception
+     */
+    private static void injectObjectNode(Worklet worklet, WorkletDescription workletDescription, Field field,
+                                         StaticDataModel model) throws WorkflowException {
+
+        ObjectNode objNode = ((JsonDataModelTree) workletDescription.data()).objectAt(model.path());
+        if (Objects.isNull(objNode)) {
+            if (model.optional()) {
+                return;
+            }
+            throw new WorkflowException("Invalid object node data model on (" + model.path() + ")");
+        }
+
+        if (!(Objects.equals(field.getType(), ObjectNode.class))) {
+            throw new WorkflowException("Target field (" + field + ") is not ObjectNode");
+        }
+
+        try {
+            field.setAccessible(true);
+            field.set(worklet, objNode);
+        } catch (IllegalAccessException e) {
+            throw new WorkflowException(e);
+        }
+    }
+}
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/Workflow.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/Workflow.java
index 1404f9b..5073105 100644
--- a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/Workflow.java
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/Workflow.java
@@ -26,12 +26,14 @@
 
     /**
      * Id of workflow.
+     *
      * @return id
      */
     URI id();
 
     /**
      * Returns init worklet.
+     *
      * @param context workflow context
      * @return init worklet
      * @throws WorkflowException workflow exception
@@ -40,6 +42,7 @@
 
     /**
      * Returns next program counter.
+     *
      * @param context workflow context
      * @return next program counter
      * @throws WorkflowException workflow exception
@@ -48,6 +51,7 @@
 
     /**
      * Gets increased program coounter.
+     *
      * @param pc program counter
      * @return increased program counter
      * @throws WorkflowException workflow exception
@@ -56,6 +60,7 @@
 
     /**
      * Returns instance of worklet.
+     *
      * @param pc program counter
      * @return instance of worklet
      * @throws WorkflowException workflow exception
@@ -64,6 +69,7 @@
 
     /**
      * Returns instance of worklet.
+     *
      * @param workletType class name of worklet
      * @return instance of worklet
      * @throws WorkflowException workflow exception
@@ -72,8 +78,9 @@
 
     /**
      * Builds workflow context.
+     *
      * @param workplace workplace of system workflow
-     * @param data data model of system workflow context
+     * @param data      data model of system workflow context
      * @return workflow context
      * @throws WorkflowException workflow exception
      */
@@ -81,8 +88,9 @@
 
     /**
      * Builds system workflow context.
+     *
      * @param workplace workplace of system workflow
-     * @param data data model of system workflow context
+     * @param data      data model of system workflow context
      * @return system workflow context
      * @throws WorkflowException workflow exception
      */
@@ -90,13 +98,23 @@
 
     /**
      * Returns workflow attributes.
+     *
      * @return attributes
      */
     Set<WorkflowAttribute> attributes();
 
     /**
-     * Returns worklet type list.
-     * @return worklet type
+     * Returns worklet desc list.
+     *
+     * @return worklet description list
      */
-    List<String> getWorkletTypeList();
+    List<WorkletDescription> getWorkletDescList();
+
+    /**
+     * Returns worklet description.
+     * @param pc program counter
+     * @return worklet description list
+     */
+    WorkletDescription getWorkletDesc(ProgramCounter pc);
+
 }
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkflowStore.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkflowStore.java
index ac0de4d..a4274935 100644
--- a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkflowStore.java
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkflowStore.java
@@ -25,18 +25,21 @@
 
     /**
      * Registers workflow.
+     *
      * @param workflow registering workflow
      */
     void register(Workflow workflow);
 
     /**
      * Unregisters workflow.
+     *
      * @param id id of workflow
      */
     void unregister(URI id);
 
     /**
      * Gets workflow.
+     *
      * @param id id of workflow
      * @return workflow
      */
@@ -44,27 +47,32 @@
 
     /**
      * Gets all workflow.
+     *
      * @return collection of workflow
      */
     Collection<Workflow> getAll();
 
     /**
      * Registers local class loader.
+     *
      * @param loader class loader
      */
     void registerLocal(ClassLoader loader);
 
     /**
      * Unregisters local class loader.
+     *
      * @param loader class loader
      */
     void unregisterLocal(ClassLoader loader);
 
     /**
      * Gets class from registered class loaders.
+     *
      * @param name name of class
      * @return class
      * @throws ClassNotFoundException class not found exception
      */
     Class getClass(String name) throws ClassNotFoundException;
+
 }
diff --git a/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkletDescription.java b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkletDescription.java
new file mode 100644
index 0000000..71ddbe5
--- /dev/null
+++ b/apps/workflow/api/src/main/java/org/onosproject/workflow/api/WorkletDescription.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.workflow.api;
+
+
+public interface WorkletDescription {
+
+    /**
+     * Gets worklet name.
+     *
+     * @return worklet name
+     */
+    String tag();
+
+    /**
+     * Gets worklet data model.
+     *
+     * @return worklet data model
+     */
+    JsonDataModelTree data();
+
+
+}
diff --git a/apps/workflow/app/src/main/java/org/onosproject/workflow/cli/WorkFlowTestCommand.java b/apps/workflow/app/src/main/java/org/onosproject/workflow/cli/WorkFlowTestCommand.java
index 3069be6..c0a418c 100644
--- a/apps/workflow/app/src/main/java/org/onosproject/workflow/cli/WorkFlowTestCommand.java
+++ b/apps/workflow/app/src/main/java/org/onosproject/workflow/cli/WorkFlowTestCommand.java
@@ -122,8 +122,8 @@
         for (int i = 0; i <= num; i++) {
             String wpName = "test_name-" + i;
             invoke("sample.workflow-0", wpName);
-            invoke("sample.workflow-1", wpName);
-            invoke("sample.workflow-2", wpName);
+          //  invoke("sample.workflow-1", wpName);
+          //  invoke("sample.workflow-2", wpName);
         }
     }
 
diff --git a/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/ECWorkFlowStore.java b/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/ECWorkFlowStore.java
index fcb17c9..725c84e 100644
--- a/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/ECWorkFlowStore.java
+++ b/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/ECWorkFlowStore.java
@@ -19,6 +19,15 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Sets;
 import org.onlab.util.KryoNamespace;
+import org.onosproject.store.service.EventuallyConsistentMap;
+import org.onosproject.store.service.StorageService;
+import org.onosproject.store.service.WallClockTimestamp;
+import org.onosproject.workflow.api.AbstractWorkflow;
+import org.onosproject.workflow.api.ImmutableListWorkflow;
+import org.onosproject.workflow.api.Workflow;
+import org.onosproject.workflow.api.WorkflowAttribute;
+import org.onosproject.workflow.api.WorkflowStore;
+import org.onosproject.workflow.api.WorkletDescription;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
@@ -27,18 +36,10 @@
 import org.slf4j.Logger;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
-import org.onosproject.workflow.api.AbstractWorkflow;
-import org.onosproject.workflow.api.ImmutableListWorkflow;
-import org.onosproject.workflow.api.Workflow;
-import org.onosproject.workflow.api.WorkflowAttribute;
-import org.onosproject.workflow.api.WorkflowStore;
 import org.onosproject.net.group.GroupEvent;
 import org.onosproject.net.group.GroupStoreDelegate;
 import org.onosproject.store.AbstractStore;
 import org.onosproject.store.serializers.KryoNamespaces;
-import org.onosproject.store.service.EventuallyConsistentMap;
-import org.onosproject.store.service.StorageService;
-import org.onosproject.store.service.WallClockTimestamp;
 
 import java.net.URI;
 import java.util.Collection;
@@ -51,7 +52,7 @@
 
 @Component(immediate = true, service = WorkflowStore.class)
 public class ECWorkFlowStore
-    extends AbstractStore<GroupEvent, GroupStoreDelegate> implements WorkflowStore {
+        extends AbstractStore<GroupEvent, GroupStoreDelegate> implements WorkflowStore {
 
     private final Logger log = getLogger(getClass());
 
@@ -77,6 +78,7 @@
                 .register(Workflow.class)
                 .register(AbstractWorkflow.class)
                 .register(ImmutableListWorkflow.class)
+                .register(WorkletDescription.class)
                 .register(List.class)
                 .register(ImmutableList.class)
                 .register(Class.class)
@@ -101,7 +103,6 @@
     @Deactivate
     public void deactivate() {
         workflowStore.destroy();
-
         log.info("Stopped");
     }
 
diff --git a/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/WorkFlowEngine.java b/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/WorkFlowEngine.java
index 5337c59..167e1c4 100644
--- a/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/WorkFlowEngine.java
+++ b/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/WorkFlowEngine.java
@@ -49,6 +49,8 @@
 import org.onosproject.workflow.api.WorkplaceStore;
 import org.onosproject.workflow.api.WorkplaceStoreDelegate;
 import org.onosproject.workflow.api.WorkflowExecutionService;
+import org.onosproject.workflow.api.WorkletDescription;
+import org.onosproject.workflow.api.StaticDataModelInjector;
 import org.onosproject.event.AbstractListenerManager;
 import org.onosproject.event.Event;
 import org.onosproject.net.intent.WorkPartitionService;
@@ -126,6 +128,7 @@
     private TimerChain timerChain = new TimerChain();
 
     private JsonDataModelInjector dataModelInjector = new JsonDataModelInjector();
+    private StaticDataModelInjector staticDataModelInjector = new StaticDataModelInjector();
 
     public static final String APPID = "org.onosproject.workflow";
     private ApplicationId appId;
@@ -273,11 +276,11 @@
             EventTask eventtask = null;
             try {
                 eventtask = EventTask.builder()
-                    .event(event)
-                    .eventHint(eventHint)
-                    .context(context)
-                    .programCounter(pc)
-                    .build();
+                        .event(event)
+                        .eventHint(eventHint)
+                        .context(context)
+                        .programCounter(pc)
+                        .build();
             } catch (WorkflowException e) {
                 log.error("Exception: ", e);
             }
@@ -358,6 +361,7 @@
 
     /**
      * Checks whether this workflow data job is relevant to this ONOS node.
+     *
      * @param job workflow data
      * @return checking result
      */
@@ -368,6 +372,7 @@
 
     /**
      * Gets hash of the string.
+     *
      * @param str string to get a hash
      * @return hash value
      */
@@ -404,6 +409,7 @@
 
     /**
      * Initializes worklet execution.
+     *
      * @param context workflow context
      */
     private void initWorkletExecution(WorkflowContext context) {
@@ -418,6 +424,7 @@
 
     /**
      * Processes handler tasks.
+     *
      * @param tasks handler tasks
      * @return handler tasks processed
      */
@@ -440,6 +447,7 @@
 
     /**
      * Executes event task.
+     *
      * @param task event task
      * @return event task
      */
@@ -530,6 +538,7 @@
 
     /**
      * Executes event timeout task.
+     *
      * @param task event timeout task
      * @return handler task
      */
@@ -576,6 +585,14 @@
             log.trace("{} task:{}, context: {}", latestContext.name(), task, latestContext);
 
             dataModelInjector.inject(worklet, latestContext);
+
+            WorkletDescription workletDesc = workflow.getWorkletDesc(task.programCounter());
+            if (Objects.nonNull(workletDesc)) {
+                if (!(workletDesc.tag().equals("INIT") || workletDesc.tag().equals("COMPLETED"))) {
+                    staticDataModelInjector.inject(worklet, workletDesc);
+                }
+            }
+
             worklet.timeout(latestContext);
             dataModelInjector.inhale(worklet, latestContext);
 
@@ -605,6 +622,7 @@
 
     /**
      * Executes timeout task.
+     *
      * @param task time out task
      * @return handler task
      */
@@ -644,6 +662,14 @@
             log.trace("{} context: {}", latestContext.name(), latestContext);
 
             dataModelInjector.inject(worklet, latestContext);
+
+            WorkletDescription workletDesc = workflow.getWorkletDesc(task.programCounter());
+            if (Objects.nonNull(workletDesc)) {
+                if (!(workletDesc.tag().equals("INIT") || workletDesc.tag().equals("COMPLETED"))) {
+                    staticDataModelInjector.inject(worklet, workletDesc);
+                }
+            }
+
             worklet.timeout(latestContext);
             dataModelInjector.inhale(worklet, latestContext);
 
@@ -682,8 +708,8 @@
                 List<CompletableFuture<WorkflowData>> futures = operations.stream()
                         .map(
                                 x -> CompletableFuture.completedFuture(x)
-                                .thenApplyAsync(WorkFlowEngine.this::execWorkflow, workflowExecutor)
-                                .exceptionally(e -> null)
+                                        .thenApplyAsync(WorkFlowEngine.this::execWorkflow, workflowExecutor)
+                                        .exceptionally(e -> null)
                         )
                         .collect(Collectors.toList());
 
@@ -699,6 +725,7 @@
 
     /**
      * Executes workflow.
+     *
      * @param dataModelContainer workflow data model container(workflow or workplace)
      * @return
      */
@@ -715,6 +742,7 @@
 
     /**
      * Executes workflow context.
+     *
      * @param context workflow context
      * @return workflow context
      */
@@ -759,7 +787,16 @@
             log.info("{} worklet.process:{}", latestContext.name(), worklet.tag());
             log.trace("{} context: {}", latestContext.name(), latestContext);
 
+
             dataModelInjector.inject(worklet, latestContext);
+
+            WorkletDescription workletDesc = workflow.getWorkletDesc(pc);
+            if (Objects.nonNull(workletDesc)) {
+                if (!(workletDesc.tag().equals("INIT") || workletDesc.tag().equals("COMPLETED"))) {
+                    staticDataModelInjector.inject(worklet, workletDesc);
+                }
+            }
+
             worklet.process(latestContext);
             dataModelInjector.inhale(worklet, latestContext);
 
@@ -832,6 +869,7 @@
 
     /**
      * Execute workplace.
+     *
      * @param workplace workplace
      * @return workplace
      */
diff --git a/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/WorkflowManager.java b/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/WorkflowManager.java
index b1acf7f..6050183 100644
--- a/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/WorkflowManager.java
+++ b/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/WorkflowManager.java
@@ -40,6 +40,7 @@
 import org.onosproject.workflow.api.Worklet;
 import org.onosproject.workflow.api.WorkflowContext;
 import org.onosproject.workflow.api.JsonDataModel;
+import org.onosproject.workflow.api.WorkletDescription;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
@@ -174,9 +175,9 @@
 
         List<String> errors = new ArrayList<>();
 
-        for (String workletType : workflow.getWorkletTypeList()) {
+        for (WorkletDescription workletType : workflow.getWorkletDescList()) {
 
-            Worklet worklet = workflow.getWorkletInstance(workletType);
+            Worklet worklet = workflow.getWorkletInstance(workletType.tag());
             if (Worklet.Common.COMPLETED.equals(worklet) || Worklet.Common.INIT.equals(worklet)) {
                 continue;
             }
@@ -203,7 +204,8 @@
                     String path = matcher.group(1);
 
                     WorkletDataModelFieldDesc desc =
-                            new WorkletDataModelFieldDesc(workletType, path, field.getType(), jsonDataModel.optional());
+                            new WorkletDataModelFieldDesc(workletType.tag(), path, field.getType(),
+                                    jsonDataModel.optional());
 
                     WorkletDataModelFieldDesc existing = descMap.get(path);
 
@@ -296,9 +298,9 @@
             throw new WorkflowDataModelException(workflow.id(), worklowDescJson, errors);
         }
 
-        for (String workletType : workflow.getWorkletTypeList()) {
+        for (WorkletDescription workletType : workflow.getWorkletDescList()) {
 
-            Worklet worklet = workflow.getWorkletInstance(workletType);
+            Worklet worklet = workflow.getWorkletInstance(workletType.tag());
             if (Worklet.Common.COMPLETED.equals(worklet) || Worklet.Common.INIT.equals(worklet)) {
                 continue;
             }
diff --git a/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/example/SampleWorkflow.java b/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/example/SampleWorkflow.java
index 8652c39..529bfb0 100644
--- a/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/example/SampleWorkflow.java
+++ b/apps/workflow/app/src/main/java/org/onosproject/workflow/impl/example/SampleWorkflow.java
@@ -29,6 +29,8 @@
 import org.onosproject.workflow.api.WorkflowException;
 import org.onosproject.workflow.api.WorkflowService;
 import org.onosproject.workflow.api.WorkflowStore;
+import org.onosproject.workflow.api.StaticDataModel;
+import org.onosproject.workflow.api.DefaultWorkletDescription;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
@@ -64,8 +66,7 @@
         try {
             registerWorkflows();
         } catch (WorkflowException e) {
-            log.error("exception: " + e);
-            e.printStackTrace();
+            log.error("invalid workflow");
         }
     }
 
@@ -76,14 +77,17 @@
 
     /**
      * Registers example workflows.
+     *
+     * @throws WorkflowException wfex
      */
-    private void registerWorkflows() throws WorkflowException {
+    public void registerWorkflows() throws WorkflowException {
         // registering class-loader
         workflowStore.registerLocal(this.getClass().getClassLoader());
 
         // registering new workflow definition
         URI uri = URI.create("sample.workflow-0");
-        Workflow workflow = ImmutableListWorkflow.builder()
+        Workflow workflow = null;
+        workflow = ImmutableListWorkflow.builder()
                 .id(uri)
                 .chain(SampleWorklet1.class.getName())
                 .chain(SampleWorklet2.class.getName())
@@ -125,6 +129,16 @@
                 .build();
         workflowService.register(workflow);
 
+        // registering new workflow definition
+        uri = URI.create("sample.workflow-static-datamodel");
+        workflow = ImmutableListWorkflow.builder()
+                .id(uri)
+                .chain(DefaultWorkletDescription.builder()
+                        .name(SampleWorklet6.class.getName())
+                        .staticDataModel("/sample", "value")
+                        .build())
+                .build();
+        workflowService.register(workflow);
     }
 
     /**
@@ -142,8 +156,10 @@
 
         }
 
+
         /**
          * Allocates or gets data model.
+         *
          * @param context workflow context
          * @return json object node
          * @throws WorkflowException workflow exception
@@ -161,6 +177,7 @@
 
         /**
          * Gets data model.
+         *
          * @param context workflow context
          * @return json object node
          * @throws WorkflowException workflow exception
@@ -172,6 +189,7 @@
 
         /**
          * Sleeps for 'ms' milli seconds.
+         *
          * @param ms milli seconds to sleep
          */
         protected void sleep(long ms) {
@@ -198,7 +216,6 @@
             node.put("work1", "done");
             log.info("workflow-process {}-{}", context.workplaceName(), this.getClass().getSimpleName());
             sleep(30);
-
             context.completed(); //Complete the job of worklet in the process
         }
 
@@ -226,6 +243,7 @@
             node.put("work2", "done");
             log.info("workflow-process {}-{}", context.workplaceName(), this.getClass().getSimpleName());
             sleep(50);
+
             intCount++;
 
             context.waitFor(50L); //Timeout will happen after 50 milli seconds.
@@ -243,6 +261,7 @@
             sleep(50);
             return !node.has("work2");
         }
+
     }
 
     public static class SampleWorklet3 extends AbsSampleWorklet {
@@ -342,4 +361,32 @@
             return !node.has("work6");
         }
     }
+
+    /**
+     * Class for sample worklet-7 to test workflow datamodel exception.
+     */
+    public static class SampleWorklet7 extends AbsSampleWorklet {
+
+        @StaticDataModel(path = "/sample")
+        String value;
+
+        @Override
+        public void process(WorkflowContext context) throws WorkflowException {
+            ObjectNode node = getDataModel(context);
+            node.put("work7", "done");
+            log.info("inside worklet - static data model {}", value);
+            log.info("workflow-process {}-{}", context.workplaceName(), this.getClass().getSimpleName());
+            sleep(10);
+            context.completed();
+        }
+
+        @Override
+        public boolean isNext(WorkflowContext context) throws WorkflowException {
+            ObjectNode node = allocOrGetModel(context);
+            log.info("workflow-isNext {}-{}", context.workplaceName(), this.getClass().getSimpleName());
+            sleep(10);
+            return !node.has("work7");
+        }
+    }
+
 }
diff --git a/apps/workflow/ofoverlay/app/src/main/java/org/onosproject/ofoverlay/impl/OfOverlayWorkflow.java b/apps/workflow/ofoverlay/app/src/main/java/org/onosproject/ofoverlay/impl/OfOverlayWorkflow.java
index cbddfc7..2267337 100644
--- a/apps/workflow/ofoverlay/app/src/main/java/org/onosproject/ofoverlay/impl/OfOverlayWorkflow.java
+++ b/apps/workflow/ofoverlay/app/src/main/java/org/onosproject/ofoverlay/impl/OfOverlayWorkflow.java
@@ -21,6 +21,8 @@
 import org.onosproject.workflow.api.WorkflowExecutionService;
 import org.onosproject.workflow.api.WorkflowStore;
 import org.onosproject.workflow.api.WorkplaceStore;
+import org.onosproject.workflow.api.DefaultWorkletDescription;
+import org.onosproject.workflow.api.WorkflowException;
 import org.osgi.service.component.annotations.Activate;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Deactivate;
@@ -57,6 +59,8 @@
 
     private ScheduledExecutorService eventMapTriggerExecutor;
 
+    private static final String BRIDGE_NAME = "/bridgeName";
+
     @Activate
     public void activate() {
         log.info("Activated");
@@ -77,108 +81,117 @@
      * Registers workflows.
      */
     private void registerWorkflows() {
-        // registering class-loader
-        workflowStore.registerLocal(this.getClass().getClassLoader());
+        try {
+            // registering class-loader
+            workflowStore.registerLocal(this.getClass().getClassLoader());
 
-        // registering new workflow definition
-        URI uri = URI.create("of-overlay.workflow-nova");
-        Workflow workflow = ImmutableListWorkflow.builder()
-                .id(uri)
-                //.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
-                .chain(Ovs.CreateOvsdbDevice.class.getName())
-                .chain(Ovs.UpdateOvsVersion.class.getName())
-                .chain(Ovs.UpdateOverlayBridgeId.class.getName())
-                .chain(Ovs.CreateOverlayBridge.class.getName())
-                .chain(Ovs.UpdateUnderlayBridgeId.class.getName())
-                .chain(Ovs.CreateUnderlayBridge.class.getName())
-                .chain(Ovs.CreateOverlayBridgeVxlanPort.class.getName())
-                .chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
-                .chain(Ovs.ConfigureUnderlayBridgeLocalIp.class.getName())
-                .build();
-        workflowStore.register(workflow);
+            // registering new workflow definition
+            URI uri = URI.create("of-overlay.workflow-nova");
+            Workflow workflow = ImmutableListWorkflow.builder()
+                    .id(uri)
+                    //.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
+                    .chain(Ovs.CreateOvsdbDevice.class.getName())
+                    .chain(Ovs.UpdateOvsVersion.class.getName())
+                    .chain(Ovs.UpdateOverlayBridgeId.class.getName())
+                    .chain(DefaultWorkletDescription.builder().name(Ovs.CreateBridge.class.getName())
+                            .staticDataModel(BRIDGE_NAME, "br-int")
+                            .build())
+                    .chain(Ovs.UpdateUnderlayBridgeId.class.getName())
+                    .chain(DefaultWorkletDescription.builder().name(Ovs.CreateBridge.class.getName())
+                            .staticDataModel(BRIDGE_NAME, "br-phy")
+                            .build())
+                    .chain(Ovs.CreateOverlayBridgeVxlanPort.class.getName())
+                    .chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
+                    .chain(Ovs.ConfigureUnderlayBridgeLocalIp.class.getName())
+                    .build();
 
-        // registering new workflow definition based on multi-event handling
-        uri = URI.create("of-overlay.workflow-nova-multiEvent-test");
-        workflow = ImmutableListWorkflow.builder()
-                .id(uri)
-                //.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
-                .chain(Ovs.CreateOvsdbDevice.class.getName())
-                .chain(Ovs.UpdateOvsVersion.class.getName())
-                .chain(Ovs.UpdateOverlayBridgeId.class.getName())
-                .chain(Ovs.CreateOverlayBridgeMultiEvent.class.getName())
-                .chain(Ovs.UpdateUnderlayBridgeId.class.getName())
-                .chain(Ovs.CreateUnderlayBridge.class.getName())
-                .chain(Ovs.CreateOverlayBridgeVxlanPort.class.getName())
-                .chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
-                .chain(Ovs.ConfigureUnderlayBridgeLocalIp.class.getName())
-                .build();
-        workflowStore.register(workflow);
+            workflowStore.register(workflow);
 
-        uri = URI.create("of-overlay.clean-workflow-nova");
-        workflow = ImmutableListWorkflow.builder()
-                .id(uri)
-                //.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
-                .chain(Ovs.DeleteOverlayBridgeConfig.class.getName())
-                .chain(Ovs.RemoveOverlayBridgeOfDevice.class.getName())
-                .chain(Ovs.DeleteUnderlayBridgeConfig.class.getName())
-                .chain(Ovs.RemoveUnderlayBridgeOfDevice.class.getName())
-                .chain(Ovs.RemoveOvsdbDevice.class.getName())
-                .build();
-        workflowStore.register(workflow);
+            // registering new workflow definition based on multi-event handling
+            uri = URI.create("of-overlay.workflow-nova-multiEvent-test");
+            workflow = ImmutableListWorkflow.builder()
+                    .id(uri)
+                    //.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
+                    .chain(Ovs.CreateOvsdbDevice.class.getName())
+                    .chain(Ovs.UpdateOvsVersion.class.getName())
+                    .chain(Ovs.UpdateOverlayBridgeId.class.getName())
+                    .chain(Ovs.CreateOverlayBridgeMultiEvent.class.getName())
+                    .chain(Ovs.UpdateUnderlayBridgeId.class.getName())
+                    .chain(Ovs.CreateUnderlayBridge.class.getName())
+                    .chain(Ovs.CreateOverlayBridgeVxlanPort.class.getName())
+                    .chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
+                    .chain(Ovs.ConfigureUnderlayBridgeLocalIp.class.getName())
+                    .build();
+            workflowStore.register(workflow);
 
-        uri = URI.create("of-overlay.clean-workflow-nova-waitAll-Bridge-Del");
-        workflow = ImmutableListWorkflow.builder()
-                .id(uri)
-                //.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
-                .chain(Ovs.DeleteOverlayBridgeConfig.class.getName())
-                .chain(Ovs.DeleteUnderlayBridgeConfig.class.getName())
-                .chain(Ovs.RemoveBridgeOfDevice.class.getName())
-                .chain(Ovs.RemoveOvsdbDevice.class.getName())
-                .build();
-        workflowStore.register(workflow);
+            uri = URI.create("of-overlay.clean-workflow-nova");
+            workflow = ImmutableListWorkflow.builder()
+                    .id(uri)
+                    //.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
+                    .chain(Ovs.DeleteOverlayBridgeConfig.class.getName())
+                    .chain(Ovs.RemoveOverlayBridgeOfDevice.class.getName())
+                    .chain(Ovs.DeleteUnderlayBridgeConfig.class.getName())
+                    .chain(Ovs.RemoveUnderlayBridgeOfDevice.class.getName())
+                    .chain(Ovs.RemoveOvsdbDevice.class.getName())
+                    .build();
+            workflowStore.register(workflow);
 
-        uri = URI.create("of-overlay.workflow-ovs-leaf");
-        workflow = ImmutableListWorkflow.builder()
-                .id(uri)
-                .chain(Ovs.CreateOvsdbDevice.class.getName())
-                .chain(Ovs.UpdateOvsVersion.class.getName())
-                .chain(Ovs.UpdateUnderlayBridgeId.class.getName())
-                .chain(Ovs.CreateUnderlayBridge.class.getName())
-                .chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
-                .build();
-        workflowStore.register(workflow);
+            uri = URI.create("of-overlay.clean-workflow-nova-waitAll-Bridge-Del");
+            workflow = ImmutableListWorkflow.builder()
+                    .id(uri)
+                    //.attribute(WorkflowAttribute.REMOVE_AFTER_COMPLETE)
+                    .chain(Ovs.DeleteOverlayBridgeConfig.class.getName())
+                    .chain(Ovs.DeleteUnderlayBridgeConfig.class.getName())
+                    .chain(Ovs.RemoveBridgeOfDevice.class.getName())
+                    .chain(Ovs.RemoveOvsdbDevice.class.getName())
+                    .build();
+            workflowStore.register(workflow);
 
-        uri = URI.create("of-overlay.workflow-ovs-spine");
-        workflow = ImmutableListWorkflow.builder()
-                .id(uri)
-                .chain(Ovs.CreateOvsdbDevice.class.getName())
-                .chain(Ovs.UpdateOvsVersion.class.getName())
-                .chain(Ovs.UpdateUnderlayBridgeId.class.getName())
-                .chain(Ovs.CreateUnderlayBridge.class.getName())
-                .chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
-                .build();
-        workflowStore.register(workflow);
+            uri = URI.create("of-overlay.workflow-ovs-leaf");
+            workflow = ImmutableListWorkflow.builder()
+                    .id(uri)
+                    .chain(Ovs.CreateOvsdbDevice.class.getName())
+                    .chain(Ovs.UpdateOvsVersion.class.getName())
+                    .chain(Ovs.UpdateUnderlayBridgeId.class.getName())
+                    .chain(Ovs.CreateUnderlayBridge.class.getName())
+                    .chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
+                    .build();
+            workflowStore.register(workflow);
 
-        deviceService.addListener(
-                event -> {
-                    // trigger EventTask for DeviceEvent
-                    eventMapTriggerExecutor.submit(
-                            () -> workflowExecutionService.eventMapTrigger(
-                                    event,
-                                    // event hint supplier
-                                    (ev) -> {
-                                        if (ev == null || ev.subject() == null) {
-                                            return null;
+            uri = URI.create("of-overlay.workflow-ovs-spine");
+            workflow = ImmutableListWorkflow.builder()
+                    .id(uri)
+                    .chain(Ovs.CreateOvsdbDevice.class.getName())
+                    .chain(Ovs.UpdateOvsVersion.class.getName())
+                    .chain(Ovs.UpdateUnderlayBridgeId.class.getName())
+                    .chain(Ovs.CreateUnderlayBridge.class.getName())
+                    .chain(Ovs.AddPhysicalPortsOnUnderlayBridge.class.getName())
+                    .build();
+            workflowStore.register(workflow);
+
+            deviceService.addListener(
+                    event -> {
+                        // trigger EventTask for DeviceEvent
+                        eventMapTriggerExecutor.submit(
+                                () -> workflowExecutionService.eventMapTrigger(
+                                        event,
+                                        // event hint supplier
+                                        (ev) -> {
+                                            if (ev == null || ev.subject() == null) {
+                                                return null;
+                                            }
+                                            String hint = event.subject().id().toString();
+                                            log.debug("hint: {}", hint);
+                                            return hint;
                                         }
-                                        String hint = event.subject().id().toString();
-                                        log.debug("hint: {}", hint);
-                                        return hint;
-                                    }
-                            )
-                    );
-                }
-        );
+                                )
+                        );
+                    }
+            );
 
+        } catch (WorkflowException e) {
+            e.printStackTrace();
+        }
     }
 
 }
diff --git a/apps/workflow/ofoverlay/app/src/main/java/org/onosproject/ofoverlay/impl/Ovs.java b/apps/workflow/ofoverlay/app/src/main/java/org/onosproject/ofoverlay/impl/Ovs.java
index ad56d52..ccbc182 100644
--- a/apps/workflow/ofoverlay/app/src/main/java/org/onosproject/ofoverlay/impl/Ovs.java
+++ b/apps/workflow/ofoverlay/app/src/main/java/org/onosproject/ofoverlay/impl/Ovs.java
@@ -59,6 +59,7 @@
 import org.onosproject.workflow.api.JsonDataModel;
 import org.onosproject.workflow.api.WorkflowContext;
 import org.onosproject.workflow.api.WorkflowException;
+import org.onosproject.workflow.api.StaticDataModel;
 import org.onosproject.workflow.model.accessinfo.SshAccessInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -83,6 +84,7 @@
     private static final Logger log = LoggerFactory.getLogger(Ovs.class);
 
     private static final String MODEL_MGMT_IP = "/mgmtIp";
+    private static final String BRIDGE_NAME = "/bridgeName";
     private static final String MODEL_OVSDB_PORT = "/ovsdbPort";
     private static final String MODEL_OVS_VERSION = "/ovsVersion";
     private static final String MODEL_OVS_DATAPATH_TYPE = "/ovsDatapathType";
@@ -535,6 +537,108 @@
         }
     }
 
+
+    public static class CreateBridge extends AbstractWorklet {
+
+        @StaticDataModel(path = BRIDGE_NAME)
+        String bridgeName;
+
+        @JsonDataModel(path = MODEL_MGMT_IP)
+        String strMgmtIp;
+
+        @JsonDataModel(path = MODEL_OVSDB_PORT)
+        Integer intOvsdbPort;
+
+        @JsonDataModel(path = MODEL_OVS_DATAPATH_TYPE)
+        String strOvsDatapath;
+
+        @JsonDataModel(path = MODEL_OF_DEVID_OVERLAY_BRIDGE, optional = true)
+        String strOfDevId;
+
+        @Override
+        public boolean isNext(WorkflowContext context) throws WorkflowException {
+
+            check(strOfDevId != null, "invalid strOfDevIdUnderlay");
+            return !OvsUtil.isAvailableBridge(context, DeviceId.deviceId(strOfDevId));
+        }
+
+        @Override
+        public void process(WorkflowContext context) throws WorkflowException {
+
+            check(strOfDevId != null, "invalid strOfDevIdOverlay");
+            BridgeConfig bridgeConfig = OvsUtil.getOvsdbBehaviour(context, strMgmtIp, BridgeConfig.class);
+            List<ControllerInfo> ofControllers = OvsUtil.getOpenflowControllerInfoList(context);
+            DeviceId ofDeviceId = DeviceId.deviceId(strOfDevId);
+
+            if (ofControllers == null || ofControllers.size() == 0) {
+                throw new WorkflowException("Invalid of controllers");
+            }
+
+            Optional<BridgeDescription> optBd = OvsUtil.getBridgeDescription(bridgeConfig, bridgeName);
+            if (!optBd.isPresent()) {
+
+                // If bridge does not exist, just creates a new bridge.
+                context.waitCompletion(DeviceEvent.class, ofDeviceId.toString(),
+                        () -> OvsUtil.createBridge(bridgeConfig,
+                                bridgeName,
+                                OvsUtil.bridgeDatapathId(ofDeviceId),
+                                ofControllers,
+                                OvsUtil.buildOvsDatapathType(strOvsDatapath)),
+                        TIMEOUT_DEVICE_CREATION_MS
+                );
+                return;
+
+            } else {
+                BridgeDescription bd = optBd.get();
+                if (OvsUtil.isEqual(ofControllers, bd.controllers())) {
+                    log.error("{} has valid controller setting({})", bridgeName, bd.controllers());
+                    context.completed();
+                    return;
+                }
+
+                OvsdbClientService ovsdbClient = OvsUtil.getOvsdbClient(context, strMgmtIp, intOvsdbPort);
+                if (ovsdbClient == null || !ovsdbClient.isConnected()) {
+                    throw new WorkflowException("Invalid ovsdb client for " + strMgmtIp);
+                }
+
+                // If controller settings are not matched, set controller with valid controller information.
+                context.waitCompletion(DeviceEvent.class, ofDeviceId.toString(),
+                        () -> ovsdbClient.setControllersWithDeviceId(bd.deviceId().get(), ofControllers),
+                        TIMEOUT_DEVICE_CREATION_MS
+                );
+                return;
+            }
+        }
+
+        @Override
+        public boolean isCompleted(WorkflowContext context, Event event)throws WorkflowException {
+            if (!(event instanceof DeviceEvent)) {
+                return false;
+            }
+            DeviceEvent deviceEvent = (DeviceEvent) event;
+            Device device = deviceEvent.subject();
+            switch (deviceEvent.type()) {
+                case DEVICE_ADDED:
+                case DEVICE_AVAILABILITY_CHANGED:
+                case DEVICE_UPDATED:
+                    return context.getService(DeviceService.class).isAvailable(device.id());
+                default:
+                    return false;
+            }
+        }
+
+        @Override
+        public void timeout(WorkflowContext context) throws WorkflowException {
+            if (!isNext(context)) {
+                context.completed(); //Complete the job of worklet by timeout
+            } else {
+                super.timeout(context);
+            }
+        }
+
+    }
+
+
     /**
      * Work-let class for creating overlay openflow bridge.
      */