inbandtelemetry REST

This patch extends the in-band-telemetry application with a REST API to provide GET/POST/DELETE
in-band domains (IntIntents)

Change-Id: I50f50edb03d262c42b4daae1c1be440aca1a6605
diff --git a/apps/inbandtelemetry/api/BUILD b/apps/inbandtelemetry/api/BUILD
index 93d94d3..4c20983 100644
--- a/apps/inbandtelemetry/api/BUILD
+++ b/apps/inbandtelemetry/api/BUILD
@@ -1,8 +1,14 @@
-COMPILE_DEPS = CORE_DEPS + KRYO + [
+COMPILE_DEPS = CORE_DEPS + JACKSON + REST + KRYO + [
+    "@jersey_client//jar",
     "//core/store/serializers:onos-core-serializers",
 ]
 
 osgi_jar_with_tests(
+    api_description = "REST API for Int",
+    api_package = "org.onosproject.inbandtelemetry.rest",
+    api_title = "INT REST",
+    api_version = "1.0",
     test_deps = TEST_ADAPTERS,
+    web_context = "/onos/int",
     deps = COMPILE_DEPS,
 )
diff --git a/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/api/package-info.java b/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/api/package-info.java
index 9e80ee5..69ff95f 100644
--- a/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/api/package-info.java
+++ b/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/api/package-info.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015-present Open Networking Foundation
+ * Copyright 2021-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.
@@ -15,7 +15,6 @@
  */
 
 /**
- * Service to control a network of devices capable of collecting and exporting
- * data plane telemetry via in-band mechanism.
+ * Implementation REST for in-band-telemetry service.
  */
-package org.onosproject.inbandtelemetry.api;
+package org.onosproject.inbandtelemetry.api;
\ No newline at end of file
diff --git a/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/rest/IntIntentCodec.java b/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/rest/IntIntentCodec.java
new file mode 100644
index 0000000..e91e180
--- /dev/null
+++ b/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/rest/IntIntentCodec.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2021-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.inbandtelemetry.rest;
+
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.inbandtelemetry.api.IntIntent;
+import org.onosproject.net.behaviour.inbandtelemetry.IntMetadataType;
+import org.onosproject.net.flow.TrafficSelector;
+
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+
+/**
+ * IntIntent JSON codec.
+ */
+public final class IntIntentCodec extends JsonCodec<IntIntent> {
+
+    // JSON field names
+    private static final String METADATA_TYPES = "metadataTypes";
+    private static final String HEADER_TYPE = "headerType";
+    private static final String TELEMETRY_MODE = "telemetryMode";
+    private static final String REPORT_TYPES = "reportTypes";
+    private static final String SELECTOR = "selector";
+
+
+    @Override
+    public ObjectNode encode(IntIntent intIntent, CodecContext context) {
+        checkNotNull(intIntent, "intIntent cannot be null");
+        ObjectNode result = context.mapper().createObjectNode();
+        ArrayNode metadataTypes = context.mapper().createArrayNode();
+        ArrayNode reportTypes = context.mapper().createArrayNode();
+        intIntent.reportTypes().forEach(reportType -> {
+            reportTypes.add(reportType.toString());
+        });
+        intIntent.metadataTypes().forEach(intMetadataType -> {
+            metadataTypes.add(intMetadataType.toString());
+        });
+        result.put(HEADER_TYPE, intIntent.headerType().toString())
+                .put(TELEMETRY_MODE, intIntent.telemetryMode().toString());
+        result.set(REPORT_TYPES, reportTypes);
+        result.set(METADATA_TYPES, metadataTypes);
+        result.set(SELECTOR, context.codec(TrafficSelector.class).encode(intIntent.selector(), context));
+        return result;
+    }
+    @Override
+    public IntIntent decode(ObjectNode json, CodecContext context) {
+        if (json == null || !json.isObject()) {
+            return null;
+        }
+        IntIntent.Builder resultBuilder = new IntIntent.Builder();
+        resultBuilder.withHeaderType(IntIntent.IntHeaderType.valueOf(json.findValue(HEADER_TYPE).asText()));
+        resultBuilder.withTelemetryMode(IntIntent.TelemetryMode.valueOf(json.findValue(TELEMETRY_MODE).asText()));
+
+        JsonCodec<TrafficSelector> selectorCodec = context.codec(TrafficSelector.class);
+        resultBuilder.withSelector(selectorCodec.decode((ObjectNode) json.findValue(SELECTOR), context));
+        json.findValue(METADATA_TYPES).forEach(metaNode -> {
+                resultBuilder.withMetadataType(IntMetadataType.valueOf(metaNode.asText()));
+        });
+        json.findValues(REPORT_TYPES).forEach(jsonNode -> {
+            resultBuilder.withReportType(IntIntent.IntReportType.valueOf(jsonNode.asText()));
+        });
+        return resultBuilder.build();
+    }
+
+}
+
diff --git a/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/rest/IntWebApplication.java b/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/rest/IntWebApplication.java
new file mode 100644
index 0000000..e74388d
--- /dev/null
+++ b/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/rest/IntWebApplication.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2021-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.inbandtelemetry.rest;
+
+import org.onlab.rest.AbstractWebApplication;
+
+import java.util.Set;
+
+/**
+ * Inbandtelemetry web application.
+ */
+public class IntWebApplication extends AbstractWebApplication {
+    @Override
+    public Set<Class<?>> getClasses() {
+        return getClasses(IntWebResource.class);
+    }
+}
diff --git a/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/rest/IntWebResource.java b/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/rest/IntWebResource.java
new file mode 100644
index 0000000..4f5cd1c
--- /dev/null
+++ b/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/rest/IntWebResource.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2021-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.inbandtelemetry.rest;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import org.onosproject.inbandtelemetry.api.IntIntent;
+import org.onosproject.inbandtelemetry.api.IntIntentId;
+import org.onosproject.inbandtelemetry.api.IntService;
+import org.onosproject.rest.AbstractWebResource;
+
+
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.GET;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.POST;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.Produces;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import javax.ws.rs.core.UriBuilder;
+import javax.ws.rs.core.MediaType;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+
+import static org.onlab.util.Tools.nullIsNotFound;
+import static org.onlab.util.Tools.readTreeFromStream;
+
+
+/**
+ * Query and program intIntents.
+ */
+@Path("intIntent")
+public class IntWebResource extends AbstractWebResource {
+    @Context
+    private UriInfo uriInfo;
+
+    private static final String INTS = "IntIntents";
+    private static final String INT = "IntIntent";
+    static final String ID = "id";
+    private static final String INT_NOT_FOUND = "IntIntent is not found for ";
+
+    private final ObjectNode root = mapper().createObjectNode();
+
+    /**
+     * Gets all IntIntents. Returns array of all IntIntents in the system.
+     * @return 200 OK with a collection of IntIntents
+     */
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getIntents() {
+        ArrayNode intsNode = root.putArray(INTS);
+        IntService service = get(IntService.class);
+        Map<IntIntentId, IntIntent> intIntents = service.getIntIntents();
+        if (!intIntents.isEmpty()) {
+            intIntents.entrySet().forEach(intIntentEntry -> {
+                intsNode.add(codec(IntIntent.class).encode(intIntentEntry.getValue(), this)
+                        .put(ID, intIntentEntry.getKey().id()));
+                }
+            );
+        }
+        return ok(root).build();
+    }
+
+    /**
+     * Get an IntIntent. Returns an IntIntent in the system.
+     * @param  id IntIntentId
+     * @return 200 OK with a IntIntent
+     */
+    @GET
+    @Produces(MediaType.APPLICATION_JSON)
+    @Path("{id}")
+    public Response getIntent(@PathParam("id") String id) {
+        ArrayNode intsNode = root.putArray(INT);
+        IntService service = get(IntService.class);
+        final IntIntent intIntent = nullIsNotFound(service.getIntIntent(IntIntentId.valueOf(Long.parseLong(id))),
+                INT_NOT_FOUND + id);
+        intsNode.add(codec(IntIntent.class).encode(intIntent, this));
+        return ok(root).build();
+    }
+
+    /**
+     * Creates new IntIntent. Creates and installs a new IntIntent.
+     *
+     * @param stream IntIntent JSON
+     * @return status of the request - CREATED if the JSON is correct,
+     * BAD_REQUEST if the JSON is invalid
+     * @onos.rsModel Int
+     */
+    @POST
+    @Consumes(MediaType.APPLICATION_JSON)
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response createIntent(InputStream stream) {
+        IntService service = get(IntService.class);
+        try {
+            ObjectNode jsonTree = readTreeFromStream(mapper(), stream);
+            IntIntent intIntent = codec(IntIntent.class).decode(jsonTree, this);
+            IntIntentId intIntentId = service.installIntIntent(intIntent);
+            UriBuilder locationBuilder = uriInfo.getBaseUriBuilder()
+                    .path(INT)
+                    .path(Long.toString(intIntentId.id()));
+            return Response
+                    .created(locationBuilder.build())
+                    .build();
+
+            } catch (IOException e) {
+            throw new IllegalArgumentException(e.getMessage());
+        }
+
+    }
+
+    /**
+     * Removes the specified IntIntent.
+     *
+     * @param  id InIntentId
+     * @return 204 NO CONTENT
+     */
+    @DELETE
+    @Path("{id}")
+    public Response deleteIntent(@PathParam("id") String id) {
+        IntService service = get(IntService.class);
+        service.removeIntIntent(IntIntentId.valueOf(Long.parseLong(id)));
+        return Response.noContent().build();
+    }
+
+}
diff --git a/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/rest/package-info.java b/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/rest/package-info.java
new file mode 100644
index 0000000..8bb00c6
--- /dev/null
+++ b/apps/inbandtelemetry/api/src/main/java/org/onosproject/inbandtelemetry/rest/package-info.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2021-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.
+ */
+
+/**
+ * Implementation REST for INT service.
+ */
+package org.onosproject.inbandtelemetry.rest;
\ No newline at end of file
diff --git a/apps/inbandtelemetry/api/src/main/resources/definitions/Int.json b/apps/inbandtelemetry/api/src/main/resources/definitions/Int.json
new file mode 100644
index 0000000..950d3cd
--- /dev/null
+++ b/apps/inbandtelemetry/api/src/main/resources/definitions/Int.json
@@ -0,0 +1,129 @@
+{
+  "type": "object",
+  "title": "INT Intents",
+
+  "required": [
+    "INT Intents"
+  ],
+  "properties": {
+    "intintent": {
+      "type": "array",
+      "xml": {
+        "name": "Ints",
+        "wrapped": true
+      },
+      "items": {
+        "type": "object",
+        "title": "int",
+        "required": [
+          "selector",
+          "metadataTypes",
+          "headerType",
+          "reportTypes",
+          "telemetryMode"
+        ],
+        "properties": {
+          "selector": {
+            "type": "object",
+            "title": "selector",
+            "required": [
+              "criteria"
+            ],
+            "properties": {
+              "criteria": {
+                "type": "array",
+                "xml": {
+                  "name": "criteria",
+                  "wrapped": true
+                },
+                "items": {
+                  "type": "object",
+                  "title": "criteria",
+                  "properties": {
+                    "type": {
+                      "type": "string",
+                      "description": "Ethernet field name",
+                      "example": "ETH_TYPE"
+                    },
+                    "ip": {
+                      "type": "string",
+                      "example": "10.1.1.0/24",
+                      "description": "IP source address"
+                    },
+                    "tcpPort": {
+                      "type": "integer",
+                      "format": "uint16",
+                      "example": 1,
+                      "description": "TCP source address"
+                    },
+                    "udpPort": {
+                      "type": "uint16",
+                      "format": "uint16",
+                      "example": 1,
+                      "description": "UDP source address"
+                    }
+                  }
+                }
+              }
+            }
+          },
+          "headerType": {
+            "type": "string",
+             "enum": [
+               "HOP_BY_HOP",
+               "DESTINATION"
+            ],
+            "example": "HOP_BY_HOP"
+          },
+          "telemetryMode": {
+            "type": "string",
+            "enum": [
+              "POSTCARD",
+              "INBAND_TELEMETRY"
+            ],
+            "example": "INBAND_TELEMETRY"
+          },
+          "metadataTypes": {
+            "type": "array",
+            "xml": {
+              "name": "metadataTypes",
+              "wrapped": true
+            },
+            "items": {
+              "type": "string",
+              "enum": [
+                "SWITCH_ID",
+                "L1_PORT_ID",
+                "HOP_LATENCY",
+                "QUEUE_OCCUPANCY",
+                "INGRESS_TIMESTAMP",
+                "EGRESS_TIMESTAMP",
+                "L2_PORT_ID",
+                "EGRESS_TX_UTIL"
+              ],
+              "example": "SWITCH_ID"
+            }
+          },
+          "reportTypes": {
+            "type": "array",
+            "xml": {
+              "name": "reportTypes",
+              "wrapped": true
+            },
+            "items": {
+              "type": "string",
+              "enum": [
+                "TRACKED_FLOW",
+                "DROPPED_PACKET",
+                "CONGESTED_QUEUE"
+              ],
+              "example": "TRACKED_FLOW"
+            }
+          }
+        }
+      }
+    }
+  }
+}
+
+
diff --git a/apps/inbandtelemetry/api/src/main/webapp/WEB-INF/web.xml b/apps/inbandtelemetry/api/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 0000000..40cc7f0
--- /dev/null
+++ b/apps/inbandtelemetry/api/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2020-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.
+  -->
+<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
+         id="ONOS" version="2.5">
+    <display-name> INT REST API v1.0</display-name>
+
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Secured</web-resource-name>
+            <url-pattern>/*</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>admin</role-name>
+            <role-name>viewer</role-name>
+        </auth-constraint>
+    </security-constraint>
+
+    <security-role>
+        <role-name>admin</role-name>
+        <role-name>viewer</role-name>
+    </security-role>
+
+    <login-config>
+        <auth-method>BASIC</auth-method>
+        <realm-name>karaf</realm-name>
+    </login-config>
+
+    <servlet>
+        <servlet-name>JAX-RS Service</servlet-name>
+        <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
+        <init-param>
+            <param-name>javax.ws.rs.Application</param-name>
+            <param-value>org.onosproject.inbandtelemetry.rest.IntWebApplication</param-value>
+        </init-param>
+        <load-on-startup>1</load-on-startup>
+    </servlet>
+
+    <servlet-mapping>
+        <servlet-name>JAX-RS Service</servlet-name>
+        <url-pattern>/*</url-pattern>
+    </servlet-mapping>
+</web-app>
diff --git a/apps/inbandtelemetry/impl/src/main/java/org/onosproject/inbandtelemetry/impl/SimpleIntManager.java b/apps/inbandtelemetry/impl/src/main/java/org/onosproject/inbandtelemetry/impl/SimpleIntManager.java
index bf7dc18..6473fa1 100644
--- a/apps/inbandtelemetry/impl/src/main/java/org/onosproject/inbandtelemetry/impl/SimpleIntManager.java
+++ b/apps/inbandtelemetry/impl/src/main/java/org/onosproject/inbandtelemetry/impl/SimpleIntManager.java
@@ -19,8 +19,10 @@
 import com.google.common.util.concurrent.Striped;
 import org.onlab.util.KryoNamespace;
 import org.onlab.util.SharedScheduledExecutors;
+import org.onosproject.codec.CodecService;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
+import org.onosproject.inbandtelemetry.rest.IntIntentCodec;
 import org.onosproject.net.behaviour.inbandtelemetry.IntReportConfig;
 import org.onosproject.net.behaviour.inbandtelemetry.IntMetadataType;
 import org.onosproject.net.behaviour.inbandtelemetry.IntDeviceConfig;
@@ -125,6 +127,9 @@
     @Reference(cardinality = ReferenceCardinality.MANDATORY)
     protected NetworkConfigRegistry netcfgRegistry;
 
+    @Reference(cardinality = ReferenceCardinality.MANDATORY)
+    protected CodecService codecService;
+
     private final Striped<Lock> deviceLocks = Striped.lock(10);
 
     private final ConcurrentMap<DeviceId, ScheduledFuture<?>> scheduledDeviceTasks = Maps.newConcurrentMap();
@@ -173,7 +178,7 @@
                 .register(IntIntent.TelemetryMode.class)
                 .register(IntDeviceConfig.class)
                 .register(IntDeviceConfig.TelemetrySpec.class);
-
+        codecService.registerCodec(IntIntent.class, new IntIntentCodec());
         devicesToConfigure = storageService.<DeviceId, Long>consistentMapBuilder()
                 .withSerializer(Serializer.using(serializer.build()))
                 .withName("onos-int-devices-to-configure")
@@ -250,6 +255,7 @@
         devicesToConfigure.removeListener(devicesToConfigureListener);
         devicesToConfigure.destroy();
         devicesToConfigure = null;
+        codecService.unregisterCodec(IntIntent.class);
         // Cancel tasks (if any).
         scheduledDeviceTasks.values().forEach(f -> {
             f.cancel(true);
diff --git a/apps/inbandtelemetry/impl/src/test/java/org/onosproject/inbandtelemetry/impl/SimpleIntManagerTest.java b/apps/inbandtelemetry/impl/src/test/java/org/onosproject/inbandtelemetry/impl/SimpleIntManagerTest.java
index 7fddf3c..a44a376 100644
--- a/apps/inbandtelemetry/impl/src/test/java/org/onosproject/inbandtelemetry/impl/SimpleIntManagerTest.java
+++ b/apps/inbandtelemetry/impl/src/test/java/org/onosproject/inbandtelemetry/impl/SimpleIntManagerTest.java
@@ -34,6 +34,7 @@
 import org.onlab.packet.TpPort;
 import org.onlab.packet.VlanId;
 import org.onosproject.TestApplicationId;
+import org.onosproject.codec.CodecService;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.inbandtelemetry.api.IntIntent;
@@ -64,6 +65,7 @@
 import org.onosproject.store.service.ConsistentMap;
 import org.onosproject.store.service.StorageService;
 import org.onosproject.store.service.TestStorageService;
+import org.onosproject.codec.JsonCodec;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -132,6 +134,7 @@
     private NetworkConfigRegistry networkConfigRegistry;
     private NetworkConfigService networkConfigService;
     private NetworkConfigListener networkConfigListener;
+    private CodecService codecService = new TestCodecService();
 
 
     @Before
@@ -154,7 +157,7 @@
         manager.netcfgService = networkConfigService;
         manager.netcfgRegistry = networkConfigRegistry;
         manager.eventExecutor = MoreExecutors.newDirectExecutorService();
-
+        manager.codecService = codecService;
         expect(coreService.registerApplication(APP_NAME))
                 .andReturn(APP_ID).anyTimes();
         networkConfigRegistry.registerConfigFactory(anyObject());
@@ -427,3 +430,27 @@
                 .build();
     }
 }
+
+/**
+ * Test Codec service.
+ */
+class TestCodecService implements CodecService {
+
+    @Override
+    public Set<Class<?>> getCodecs() {
+        return null;
+    }
+
+    @Override
+    public <T> JsonCodec<T> getCodec(Class<T> entityClass) {
+        return null;
+    }
+
+    @Override
+    public <T> void registerCodec(Class<T> entityClass, JsonCodec<T> codec) { }
+
+    @Override
+    public void unregisterCodec(Class<?> entityClass) {
+
+    }
+}