ONOS-743 - Use REST API Codecs to generate JSON for CLI commands

Change-Id: I25e0840d1af03341c638f837498c95275e6cf31b
diff --git a/cli/pom.xml b/cli/pom.xml
index 1ed1d47..2a9e922 100644
--- a/cli/pom.xml
+++ b/cli/pom.xml
@@ -41,6 +41,10 @@
             <groupId>org.onosproject</groupId>
             <artifactId>onlab-osgi</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.onosproject</groupId>
+            <artifactId>onos-core-common</artifactId>
+        </dependency>
 
         <dependency>
             <groupId>com.fasterxml.jackson.core</groupId>
diff --git a/cli/src/main/java/org/onosproject/cli/AbstractShellCommand.java b/cli/src/main/java/org/onosproject/cli/AbstractShellCommand.java
index 4dd767b..8945d62 100644
--- a/cli/src/main/java/org/onosproject/cli/AbstractShellCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/AbstractShellCommand.java
@@ -15,20 +15,24 @@
  */
 package org.onosproject.cli;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.apache.karaf.shell.commands.Option;
 import org.apache.karaf.shell.console.AbstractAction;
 import org.onlab.osgi.DefaultServiceDirectory;
 import org.onlab.osgi.ServiceNotFoundException;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.CodecService;
+import org.onosproject.codec.JsonCodec;
 import org.onosproject.core.ApplicationId;
 import org.onosproject.core.CoreService;
 import org.onosproject.net.Annotations;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
 /**
  * Base abstraction of Karaf shell commands.
  */
-public abstract class AbstractShellCommand extends AbstractAction {
+public abstract class AbstractShellCommand extends AbstractAction implements CodecContext {
 
     @Option(name = "-j", aliases = "--json", description = "Output JSON",
             required = false, multiValued = false)
@@ -129,4 +133,35 @@
         return null;
     }
 
+
+
+    private final ObjectMapper mapper = new ObjectMapper();
+
+    @Override
+    public ObjectMapper mapper() {
+        return mapper;
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public <T> JsonCodec<T> codec(Class<T> entityClass) {
+        return get(CodecService.class).getCodec(entityClass);
+    }
+
+    @Override
+    public <T> T getService(Class<T> serviceClass) {
+        return get(serviceClass);
+    }
+
+    /**
+     * Generates a Json representation of an object.
+     *
+     * @param entity object to generate JSON for
+     * @param entityClass class to format with - this chooses which codec to use
+     * @param <T> Type of the object being formatted
+     * @return JSON object representation
+     */
+    public <T> ObjectNode jsonForEntity(T entity, Class<T> entityClass) {
+        return codec(entityClass).encode(entity, this);
+    }
 }
diff --git a/cli/src/main/java/org/onosproject/cli/app/ApplicationsListCommand.java b/cli/src/main/java/org/onosproject/cli/app/ApplicationsListCommand.java
index c518b43..17cf89e 100644
--- a/cli/src/main/java/org/onosproject/cli/app/ApplicationsListCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/app/ApplicationsListCommand.java
@@ -15,9 +15,9 @@
  */
 package org.onosproject.cli.app;
 
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
+import java.util.Collections;
+import java.util.List;
+
 import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
 import org.onosproject.app.ApplicationService;
@@ -25,8 +25,9 @@
 import org.onosproject.cli.Comparators;
 import org.onosproject.core.Application;
 
-import java.util.Collections;
-import java.util.List;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
 
 import static com.google.common.collect.Lists.newArrayList;
 import static org.onosproject.app.ApplicationState.ACTIVE;
@@ -88,25 +89,12 @@
         for (Application app : apps) {
             boolean isActive = service.getState(app.id()) == ACTIVE;
             if (activeOnly && isActive || !activeOnly) {
-                result.add(json(service, mapper, app));
+                result.add(jsonForEntity(app, Application.class));
             }
         }
         return result;
     }
 
-    protected JsonNode json(ApplicationService service, ObjectMapper mapper,
-                            Application app) {
-        return mapper.createObjectNode()
-                .put("name", app.id().name())
-                .put("id", app.id().id())
-                .put("version", app.version().toString())
-                .put("description", app.description())
-                .put("origin", app.origin())
-                .put("permissions", app.permissions().toString())
-                .put("featuresRepo", app.featuresRepo().isPresent() ?
-                        app.featuresRepo().get().toString() : "")
-                .put("features", app.features().toString())
-                .put("state", service.getState(app.id()).toString());
-    }
+
 
 }
diff --git a/cli/src/main/java/org/onosproject/cli/net/ClusterLinksCommand.java b/cli/src/main/java/org/onosproject/cli/net/ClusterLinksCommand.java
index fb0c941..dc63bff 100644
--- a/cli/src/main/java/org/onosproject/cli/net/ClusterLinksCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/ClusterLinksCommand.java
@@ -43,7 +43,7 @@
         if (cluster == null) {
             error("No such cluster %s", cid);
         } else if (outputJson()) {
-            print("%s", json(service.getClusterLinks(topology, cluster)));
+            print("%s", json(this, service.getClusterLinks(topology, cluster)));
         } else {
             for (Link link : service.getClusterLinks(topology, cluster)) {
                 print(linkString(link));
diff --git a/cli/src/main/java/org/onosproject/cli/net/ClustersListCommand.java b/cli/src/main/java/org/onosproject/cli/net/ClustersListCommand.java
index 0c2d2f4..21c2732 100644
--- a/cli/src/main/java/org/onosproject/cli/net/ClustersListCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/ClustersListCommand.java
@@ -55,12 +55,11 @@
     private JsonNode json(Iterable<TopologyCluster> clusters) {
         ObjectMapper mapper = new ObjectMapper();
         ArrayNode result = mapper.createArrayNode();
-        for (TopologyCluster cluster : clusters) {
-            result.add(mapper.createObjectNode()
-                               .put("id", cluster.id().index())
-                               .put("deviceCount", cluster.deviceCount())
-                               .put("linkCount", cluster.linkCount()));
-        }
+
+        clusters.spliterator()
+                .forEachRemaining(cluster ->
+                        result.add(jsonForEntity(cluster, TopologyCluster.class)));
+
         return result;
     }
 
diff --git a/cli/src/main/java/org/onosproject/cli/net/DevicePortsListCommand.java b/cli/src/main/java/org/onosproject/cli/net/DevicePortsListCommand.java
index 3e2510c..494273c 100644
--- a/cli/src/main/java/org/onosproject/cli/net/DevicePortsListCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/DevicePortsListCommand.java
@@ -116,7 +116,7 @@
                                   .set("annotations", annotations(mapper, port.annotations())));
             }
         }
-        result.set("device", json(service, mapper, device));
+        result.set("device", jsonForEntity(device, Device.class));
         result.set("ports", ports);
         return result;
     }
diff --git a/cli/src/main/java/org/onosproject/cli/net/DevicesListCommand.java b/cli/src/main/java/org/onosproject/cli/net/DevicesListCommand.java
index 852e5f5..e40bcad 100644
--- a/cli/src/main/java/org/onosproject/cli/net/DevicesListCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/DevicesListCommand.java
@@ -15,18 +15,18 @@
  */
 package org.onosproject.cli.net;
 
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.util.Collections;
+import java.util.List;
+
 import org.apache.karaf.shell.commands.Command;
 import org.onosproject.cli.AbstractShellCommand;
 import org.onosproject.cli.Comparators;
 import org.onosproject.net.Device;
 import org.onosproject.net.device.DeviceService;
 
-import java.util.Collections;
-import java.util.List;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
 
 import static com.google.common.collect.Lists.newArrayList;
 
@@ -44,7 +44,7 @@
     protected void execute() {
         DeviceService service = get(DeviceService.class);
         if (outputJson()) {
-            print("%s", json(service, getSortedDevices(service)));
+            print("%s", json(getSortedDevices(service)));
         } else {
             for (Device device : getSortedDevices(service)) {
                 printDevice(service, device);
@@ -55,40 +55,14 @@
     /**
      * Returns JSON node representing the specified devices.
      *
-     * @param service device service
      * @param devices collection of devices
      * @return JSON node
      */
-    public static JsonNode json(DeviceService service, Iterable<Device> devices) {
+    private JsonNode json(Iterable<Device> devices) {
         ObjectMapper mapper = new ObjectMapper();
         ArrayNode result = mapper.createArrayNode();
         for (Device device : devices) {
-            result.add(json(service, mapper, device));
-        }
-        return result;
-    }
-
-    /**
-     * Returns JSON node representing the specified device.
-     *
-     * @param service device service
-     * @param mapper  object mapper
-     * @param device  infrastructure device
-     * @return JSON node
-     */
-    public static ObjectNode json(DeviceService service, ObjectMapper mapper,
-                                  Device device) {
-        ObjectNode result = mapper.createObjectNode();
-        if (device != null) {
-            result.put("id", device.id().toString())
-                    .put("available", service.isAvailable(device.id()))
-                    .put("type", device.type().toString())
-                    .put("role", service.getRole(device.id()).toString())
-                    .put("mfr", device.manufacturer())
-                    .put("hw", device.hwVersion())
-                    .put("sw", device.swVersion())
-                    .put("serial", device.serialNumber())
-                    .set("annotations", annotations(mapper, device.annotations()));
+            result.add(jsonForEntity(device, Device.class));
         }
         return result;
     }
diff --git a/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java b/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java
index dabeab9..f123df6 100644
--- a/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/FlowsListCommand.java
@@ -15,31 +15,28 @@
  */
 package org.onosproject.cli.net;
 
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedMap;
+import java.util.TreeMap;
 
 import org.apache.karaf.shell.commands.Argument;
 import org.apache.karaf.shell.commands.Command;
-import org.onosproject.core.ApplicationId;
-import org.onosproject.core.CoreService;
 import org.onosproject.cli.AbstractShellCommand;
 import org.onosproject.cli.Comparators;
+import org.onosproject.core.CoreService;
 import org.onosproject.net.Device;
 import org.onosproject.net.DeviceId;
 import org.onosproject.net.device.DeviceService;
 import org.onosproject.net.flow.FlowEntry;
 import org.onosproject.net.flow.FlowEntry.FlowEntryState;
 import org.onosproject.net.flow.FlowRuleService;
-import org.onosproject.net.flow.criteria.Criterion;
-import org.onosproject.net.flow.instructions.Instruction;
 
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.SortedMap;
-import java.util.TreeMap;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 
 import static com.google.common.collect.Lists.newArrayList;
 
@@ -73,7 +70,7 @@
         SortedMap<Device, List<FlowEntry>> flows = getSortedFlows(deviceService, service);
 
         if (outputJson()) {
-            print("%s", json(coreService, flows.keySet(), flows));
+            print("%s", json(flows.keySet(), flows));
         } else {
             flows.forEach((device, flow) -> printFlows(device, flow, coreService));
         }
@@ -82,30 +79,27 @@
     /**
      * Produces a JSON array of flows grouped by the each device.
      *
-     * @param coreService core service
      * @param devices     collection of devices to group flow by
      * @param flows       collection of flows per each device
      * @return JSON array
      */
-    private JsonNode json(CoreService coreService, Iterable<Device> devices,
+    private JsonNode json(Iterable<Device> devices,
                           Map<Device, List<FlowEntry>> flows) {
         ObjectMapper mapper = new ObjectMapper();
         ArrayNode result = mapper.createArrayNode();
         for (Device device : devices) {
-            result.add(json(coreService, mapper, device, flows.get(device)));
+            result.add(json(mapper, device, flows.get(device)));
         }
         return result;
     }
 
     // Produces JSON object with the flows of the given device.
-    private ObjectNode json(CoreService coreService, ObjectMapper mapper,
+    private ObjectNode json(ObjectMapper mapper,
                             Device device, List<FlowEntry> flows) {
         ObjectNode result = mapper.createObjectNode();
         ArrayNode array = mapper.createArrayNode();
 
-        for (FlowEntry flow : flows) {
-            array.add(json(coreService, mapper, flow));
-        }
+        flows.forEach(flow -> array.add(jsonForEntity(flow, FlowEntry.class)));
 
         result.put("device", device.id().toString())
                 .put("flowCount", flows.size())
@@ -113,37 +107,6 @@
         return result;
     }
 
-    // Produces JSON structure with the specified flow data.
-    private ObjectNode json(CoreService coreService, ObjectMapper mapper,
-                            FlowEntry flow) {
-        ObjectNode result = mapper.createObjectNode();
-        ArrayNode crit = mapper.createArrayNode();
-        for (Criterion c : flow.selector().criteria()) {
-            crit.add(c.toString());
-        }
-
-        ArrayNode instr = mapper.createArrayNode();
-        for (Instruction i : flow.treatment().allInstructions()) {
-            instr.add(i.toString());
-        }
-
-        ApplicationId appCoreId = coreService.getAppId(flow.appId());
-        String appName = appCoreId == null ?
-                Short.toString(flow.appId())
-                : appCoreId.name();
-
-        result.put("flowId", Long.toHexString(flow.id().value()))
-                .put("state", flow.state().toString())
-                .put("bytes", flow.bytes())
-                .put("packets", flow.packets())
-                .put("life", flow.life())
-                .put("tableId", flow.tableId())
-                .put("appId", appName);
-        result.set("selector", crit);
-        result.set("treatment", instr);
-        return result;
-    }
-
     /**
      * Returns the list of devices sorted using the device ID URIs.
      *
diff --git a/cli/src/main/java/org/onosproject/cli/net/HostsListCommand.java b/cli/src/main/java/org/onosproject/cli/net/HostsListCommand.java
index 10d015f..a90627e 100644
--- a/cli/src/main/java/org/onosproject/cli/net/HostsListCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/HostsListCommand.java
@@ -15,19 +15,18 @@
  */
 package org.onosproject.cli.net;
 
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.util.Collections;
+import java.util.List;
+
 import org.apache.karaf.shell.commands.Command;
 import org.onosproject.cli.AbstractShellCommand;
 import org.onosproject.cli.Comparators;
 import org.onosproject.net.Host;
 import org.onosproject.net.host.HostService;
-import org.onlab.packet.IpAddress;
 
-import java.util.Collections;
-import java.util.List;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
 
 import static com.google.common.collect.Lists.newArrayList;
 
@@ -54,30 +53,11 @@
     }
 
     // Produces JSON structure.
-    private static JsonNode json(Iterable<Host> hosts) {
+    private JsonNode json(Iterable<Host> hosts) {
         ObjectMapper mapper = new ObjectMapper();
         ArrayNode result = mapper.createArrayNode();
-        for (Host host : hosts) {
-            result.add(json(mapper, host));
-        }
-        return result;
-    }
 
-    // Produces JSON structure.
-    private static JsonNode json(ObjectMapper mapper, Host host) {
-        ObjectNode loc = LinksListCommand.json(mapper, host.location())
-                .put("time", host.location().time());
-        ArrayNode ips = mapper.createArrayNode();
-        for (IpAddress ip : host.ipAddresses()) {
-            ips.add(ip.toString());
-        }
-        ObjectNode result = mapper.createObjectNode()
-                .put("id", host.id().toString())
-                .put("mac", host.mac().toString())
-                .put("vlan", host.vlan().toString());
-        result.set("location", loc);
-        result.set("ips", ips);
-        result.set("annotations", annotations(mapper, host.annotations()));
+        hosts.forEach(host -> result.add(jsonForEntity(host, Host.class)));
         return result;
     }
 
diff --git a/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java b/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java
index a52b7e3..55b9ec9 100644
--- a/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/IntentsListCommand.java
@@ -15,16 +15,11 @@
  */
 package org.onosproject.cli.net;
 
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.util.List;
+
 import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.Option;
 import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.Link;
-import org.onosproject.net.NetworkResource;
 import org.onosproject.net.intent.ConnectivityIntent;
 import org.onosproject.net.intent.HostToHostIntent;
 import org.onosproject.net.intent.Intent;
@@ -36,8 +31,10 @@
 import org.onosproject.net.intent.PointToPointIntent;
 import org.onosproject.net.intent.SinglePointToMultiPointIntent;
 
-import java.util.List;
-import java.util.Set;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 
 /**
  * Lists the inventory of intents and their states.
@@ -393,81 +390,9 @@
     private JsonNode json(IntentService service, Iterable<Intent> intents) {
         ObjectMapper mapper = new ObjectMapper();
         ArrayNode result = mapper.createArrayNode();
-        for (Intent intent : intents) {
-            result.add(json(service, mapper, intent));
-        }
+
+        intents.forEach(intent -> result.add(jsonForEntity(intent, Intent.class)));
         return result;
     }
 
-    private JsonNode json(IntentService service, ObjectMapper mapper, Intent intent) {
-        ObjectNode result = mapper.createObjectNode()
-                .put("id", intent.id().toString())
-                .put("type", intent.getClass().getSimpleName())
-                .put("appId", intent.appId().name());
-
-        IntentState state = service.getIntentState(intent.key());
-        if (state != null) {
-            result.put("state", state.toString());
-        }
-
-        if (!intent.resources().isEmpty()) {
-            ArrayNode rnode = mapper.createArrayNode();
-            for (NetworkResource resource : intent.resources()) {
-                rnode.add(resource.toString());
-            }
-            result.set("resources", rnode);
-        }
-
-        if (intent instanceof ConnectivityIntent) {
-            ConnectivityIntent ci = (ConnectivityIntent) intent;
-            if (!ci.selector().criteria().isEmpty()) {
-                result.put("selector", ci.selector().criteria().toString());
-            }
-            if (!ci.treatment().allInstructions().isEmpty()) {
-                result.put("treatment", ci.treatment().allInstructions().toString());
-            }
-        }
-
-        if (intent instanceof PathIntent) {
-            PathIntent pi = (PathIntent) intent;
-            ArrayNode pnode = mapper.createArrayNode();
-            for (Link link : pi.path().links()) {
-                pnode.add(link.toString());
-            }
-            result.set("path", pnode);
-        } else if (intent instanceof HostToHostIntent) {
-            HostToHostIntent pi = (HostToHostIntent) intent;
-            result.set("host1", LinksListCommand.json(mapper, pi.one()));
-            result.set("host2", LinksListCommand.json(mapper, pi.two()));
-        } else if (intent instanceof PointToPointIntent) {
-            PointToPointIntent pi = (PointToPointIntent) intent;
-            result.set("ingress", LinksListCommand.json(mapper, pi.ingressPoint()));
-            result.set("egress", LinksListCommand.json(mapper, pi.egressPoint()));
-        } else if (intent instanceof MultiPointToSinglePointIntent) {
-            MultiPointToSinglePointIntent pi = (MultiPointToSinglePointIntent) intent;
-            result.set("ingress", json(mapper, pi.ingressPoints()));
-            result.set("egress", LinksListCommand.json(mapper, pi.egressPoint()));
-        } else if (intent instanceof SinglePointToMultiPointIntent) {
-            SinglePointToMultiPointIntent pi = (SinglePointToMultiPointIntent) intent;
-            result.set("ingress", LinksListCommand.json(mapper, pi.ingressPoint()));
-            result.set("egress", json(mapper, pi.egressPoints()));
-        } else if (intent instanceof LinkCollectionIntent) {
-            LinkCollectionIntent li = (LinkCollectionIntent) intent;
-            result.set("links", LinksListCommand.json(li.links()));
-        }
-
-        List<Intent> installable = service.getInstallableIntents(intent.key());
-        if (installable != null && !installable.isEmpty()) {
-            result.set("installable", json(service, installable));
-        }
-        return result;
-    }
-
-    private JsonNode json(ObjectMapper mapper, Set<ConnectPoint> connectPoints) {
-        ArrayNode result = mapper.createArrayNode();
-        for (ConnectPoint cp : connectPoints) {
-            result.add(LinksListCommand.json(mapper, cp));
-        }
-        return result;
-    }
 }
diff --git a/cli/src/main/java/org/onosproject/cli/net/LinksListCommand.java b/cli/src/main/java/org/onosproject/cli/net/LinksListCommand.java
index 99872ac..b9403a3 100644
--- a/cli/src/main/java/org/onosproject/cli/net/LinksListCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/LinksListCommand.java
@@ -15,17 +15,16 @@
  */
 package org.onosproject.cli.net;
 
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.Link;
+import org.onosproject.net.link.LinkService;
+
 import com.fasterxml.jackson.databind.JsonNode;
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.Command;
-import org.onosproject.cli.AbstractShellCommand;
-import org.onosproject.net.ConnectPoint;
-import org.onosproject.net.HostId;
-import org.onosproject.net.Link;
-import org.onosproject.net.link.LinkService;
 
 import static org.onosproject.net.DeviceId.deviceId;
 
@@ -49,7 +48,7 @@
         Iterable<Link> links = uri != null ?
                 service.getDeviceLinks(deviceId(uri)) : service.getLinks();
         if (outputJson()) {
-            print("%s", json(links));
+            print("%s", json(this, links));
         } else {
             for (Link link : links) {
                 print(linkString(link));
@@ -60,59 +59,28 @@
     /**
      * Produces a JSON array containing the specified links.
      *
+     * @param context context to use for looking up codecs
      * @param links collection of links
      * @return JSON array
      */
-    public static JsonNode json(Iterable<Link> links) {
+    public static JsonNode json(AbstractShellCommand context, Iterable<Link> links) {
         ObjectMapper mapper = new ObjectMapper();
         ArrayNode result = mapper.createArrayNode();
-        for (Link link : links) {
-            result.add(json(mapper, link));
-        }
+
+        links.forEach(link -> result.add(context.jsonForEntity(link, Link.class)));
+
         return result;
     }
 
     /**
      * Produces a JSON object for the specified link.
      *
-     * @param mapper object mapper
+     * @param context context to use for looking up codecs
      * @param link   link to encode
      * @return JSON object
      */
-    public static ObjectNode json(ObjectMapper mapper, Link link) {
-        ObjectNode result = mapper.createObjectNode();
-        result.set("src", json(mapper, link.src()));
-        result.set("dst", json(mapper, link.dst()));
-        result.put("type", link.type().toString());
-        result.put("state", link.state().toString());
-        result.set("annotations", annotations(mapper, link.annotations()));
-        return result;
-    }
-
-    /**
-     * Produces a JSON object for the specified host ID.
-     *
-     * @param mapper    object mapper
-     * @param hostId    host ID to encode
-     * @return JSON object
-     */
-    public static ObjectNode json(ObjectMapper mapper, HostId hostId) {
-        return mapper.createObjectNode()
-                .put("mac", hostId.mac().toString())
-                .put("vlanId", hostId.vlanId().toString());
-    }
-
-    /**
-     * Produces a JSON object for the specified connect point.
-     *
-     * @param mapper       object mapper
-     * @param connectPoint connection point to encode
-     * @return JSON object
-     */
-    public static ObjectNode json(ObjectMapper mapper, ConnectPoint connectPoint) {
-        return mapper.createObjectNode()
-                .put("device", connectPoint.deviceId().toString())
-                .put("port", connectPoint.port().toString());
+    public static ObjectNode json(AbstractShellCommand context, Link link) {
+         return context.jsonForEntity(link, Link.class);
     }
 
     /**
diff --git a/cli/src/main/java/org/onosproject/cli/net/PathListCommand.java b/cli/src/main/java/org/onosproject/cli/net/PathListCommand.java
index a76a878..141ae26 100644
--- a/cli/src/main/java/org/onosproject/cli/net/PathListCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/PathListCommand.java
@@ -20,6 +20,7 @@
 import com.fasterxml.jackson.databind.node.ArrayNode;
 import org.apache.karaf.shell.commands.Argument;
 import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
 import org.onosproject.net.Link;
 import org.onosproject.net.Path;
 
@@ -51,7 +52,7 @@
         init();
         Set<Path> paths = service.getPaths(topology, deviceId(src), deviceId(dst));
         if (outputJson()) {
-            print("%s", json(paths));
+            print("%s", json(this, paths));
         } else {
             for (Path path : paths) {
                 print(pathString(path));
@@ -62,16 +63,17 @@
     /**
      * Produces a JSON array containing the specified paths.
      *
+     * @param context context to use for looking up codecs
      * @param paths collection of paths
      * @return JSON array
      */
-    public static JsonNode json(Iterable<Path> paths) {
+    public static JsonNode json(AbstractShellCommand context, Iterable<Path> paths) {
         ObjectMapper mapper = new ObjectMapper();
         ArrayNode result = mapper.createArrayNode();
         for (Path path : paths) {
-            result.add(LinksListCommand.json(mapper, path)
-                               .put("cost", path.cost())
-                               .set("links", LinksListCommand.json(path.links())));
+            result.add(LinksListCommand.json(context, path)
+                    .put("cost", path.cost())
+                    .set("links", LinksListCommand.json(context, path.links())));
         }
         return result;
     }
diff --git a/cli/src/main/java/org/onosproject/cli/net/TopologyCommand.java b/cli/src/main/java/org/onosproject/cli/net/TopologyCommand.java
index b454645..e1ebd25 100644
--- a/cli/src/main/java/org/onosproject/cli/net/TopologyCommand.java
+++ b/cli/src/main/java/org/onosproject/cli/net/TopologyCommand.java
@@ -27,8 +27,6 @@
 import org.onosproject.net.topology.TopologyProvider;
 import org.onosproject.net.topology.TopologyService;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-
 /**
  * Lists summary of the current topology.
  */
@@ -64,14 +62,7 @@
 
         } else if (outputJson()) {
             print("%s",
-                    new ObjectMapper()
-                            .createObjectNode()
-                            .put("time", topology.time())
-                            .put("created", formatCreationTime(topology.creationTime()))
-                            .put("uptime", formatElapsedTime(topologyUptime))
-                            .put("deviceCount", topology.deviceCount())
-                            .put("linkCount", topology.linkCount())
-                            .put("clusterCount", topology.clusterCount()));
+                    jsonForEntity(topology, Topology.class));
         } else {
             print(FMT, formatCreationTime(topology.creationTime()),
                     formatElapsedTime(topologyUptime),
diff --git a/core/api/src/main/java/org/onosproject/codec/CodecContext.java b/core/api/src/main/java/org/onosproject/codec/CodecContext.java
index ee00fa9..272c3e9 100644
--- a/core/api/src/main/java/org/onosproject/codec/CodecContext.java
+++ b/core/api/src/main/java/org/onosproject/codec/CodecContext.java
@@ -45,6 +45,6 @@
      * @param <T>          service type
      * @return JSON codec; null if no codec available for the class
      */
-    <T> T get(Class<T> serviceClass);
+    <T> T getService(Class<T> serviceClass);
 
 }
diff --git a/core/api/src/main/java/org/onosproject/rest/AbstractWebResource.java b/core/api/src/main/java/org/onosproject/rest/AbstractWebResource.java
index ff53182..82caf08 100644
--- a/core/api/src/main/java/org/onosproject/rest/AbstractWebResource.java
+++ b/core/api/src/main/java/org/onosproject/rest/AbstractWebResource.java
@@ -60,4 +60,9 @@
         return result;
     }
 
+    @Override
+    public <T> T getService(Class<T> serviceClass) {
+        return get(serviceClass);
+    }
+
 }
diff --git a/core/api/src/test/java/org/onosproject/codec/JsonCodecTest.java b/core/api/src/test/java/org/onosproject/codec/JsonCodecTest.java
index ebe5f8e..eb04d9a 100644
--- a/core/api/src/test/java/org/onosproject/codec/JsonCodecTest.java
+++ b/core/api/src/test/java/org/onosproject/codec/JsonCodecTest.java
@@ -92,7 +92,7 @@
         }
 
         @Override
-        public <T> T get(Class<T> serviceClass) {
+        public <T> T getService(Class<T> serviceClass) {
             return null;
         }
     }
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java
index 4812154..b2cab09 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/ApplicationCodec.java
@@ -31,7 +31,7 @@
     @Override
     public ObjectNode encode(Application app, CodecContext context) {
         checkNotNull(app, "Application cannot be null");
-        ApplicationService service = context.get(ApplicationService.class);
+        ApplicationService service = context.getService(ApplicationService.class);
         ObjectNode result = context.mapper().createObjectNode()
                 .put("name", app.id().name())
                 .put("id", app.id().id())
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/ControllerNodeCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/ControllerNodeCodec.java
index 4b06ff0..65d758e 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/ControllerNodeCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/ControllerNodeCodec.java
@@ -35,7 +35,7 @@
     @Override
     public ObjectNode encode(ControllerNode node, CodecContext context) {
         checkNotNull(node, "Controller node cannot be null");
-        ClusterService service = context.get(ClusterService.class);
+        ClusterService service = context.getService(ClusterService.class);
         return context.mapper().createObjectNode()
                 .put("id", node.id().toString())
                 .put("ip", node.ip().toString())
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/CriterionCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/CriterionCodec.java
index 899ade5..3526f23 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/CriterionCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/CriterionCodec.java
@@ -117,19 +117,19 @@
     }
 
     private interface CriterionTypeFormatter {
-        ObjectNode formatCriterion(ObjectNode root, Criterion criterion);
+        ObjectNode encodeCriterion(ObjectNode root, Criterion criterion);
     }
 
     private static class FormatUnknown implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             return root;
         }
     }
 
     private static class FormatInPort implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final PortCriterion portCriterion = (PortCriterion) criterion;
             return root.put("port", portCriterion.port().toLong());
         }
@@ -137,7 +137,7 @@
 
     private static class FormatMetadata implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final MetadataCriterion metadataCriterion =
                     (MetadataCriterion) criterion;
             return root.put("metadata", metadataCriterion.metadata());
@@ -146,7 +146,7 @@
 
     private static class FormatEth implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final EthCriterion ethCriterion = (EthCriterion) criterion;
             return root.put("mac", ethCriterion.mac().toString());
         }
@@ -154,7 +154,7 @@
 
     private static class FormatEthType implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final EthTypeCriterion ethTypeCriterion =
                     (EthTypeCriterion) criterion;
             return root.put("ethType", ethTypeCriterion.ethType());
@@ -163,7 +163,7 @@
 
     private static class FormatVlanVid implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final VlanIdCriterion vlanIdCriterion =
                     (VlanIdCriterion) criterion;
             return root.put("vlanId", vlanIdCriterion.vlanId().toShort());
@@ -172,7 +172,7 @@
 
     private static class FormatVlanPcp implements CriterionTypeFormatter {
             @Override
-            public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+            public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
                 final VlanPcpCriterion vlanPcpCriterion =
                         (VlanPcpCriterion) criterion;
                 return root.put("priority", vlanPcpCriterion.priority());
@@ -181,7 +181,7 @@
 
     private static class FormatIpDscp implements CriterionTypeFormatter {
             @Override
-            public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+            public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
                 final IPDscpCriterion ipDscpCriterion =
                         (IPDscpCriterion) criterion;
                 return root.put("ipDscp", ipDscpCriterion.ipDscp());
@@ -190,7 +190,7 @@
 
     private static class FormatIpEcn implements CriterionTypeFormatter {
             @Override
-            public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+            public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
                 final IPEcnCriterion ipEcnCriterion =
                         (IPEcnCriterion) criterion;
                 return root.put("ipEcn", ipEcnCriterion.ipEcn());
@@ -199,7 +199,7 @@
 
     private static class FormatIpProto implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final IPProtocolCriterion iPProtocolCriterion =
                     (IPProtocolCriterion) criterion;
             return root.put("protocol", iPProtocolCriterion.protocol());
@@ -208,7 +208,7 @@
 
     private static class FormatIp implements CriterionTypeFormatter {
             @Override
-            public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+            public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
                 final IPCriterion iPCriterion = (IPCriterion) criterion;
                 return root.put("ip", iPCriterion.ip().toString());
         }
@@ -216,7 +216,7 @@
 
     private static class FormatTcp implements CriterionTypeFormatter {
             @Override
-            public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+            public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
                 final TcpPortCriterion tcpPortCriterion =
                         (TcpPortCriterion) criterion;
                 return root.put("tcpPort", tcpPortCriterion.tcpPort());
@@ -225,7 +225,7 @@
 
     private static class FormatUdp implements CriterionTypeFormatter {
             @Override
-            public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+            public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
                 final UdpPortCriterion udpPortCriterion =
                         (UdpPortCriterion) criterion;
                 return root.put("udpPort", udpPortCriterion.udpPort());
@@ -234,7 +234,7 @@
 
     private static class FormatSctp implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final SctpPortCriterion sctpPortCriterion =
                     (SctpPortCriterion) criterion;
             return root.put("sctpPort", sctpPortCriterion.sctpPort());
@@ -243,7 +243,7 @@
 
     private static class FormatIcmpV4Type implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final IcmpTypeCriterion icmpTypeCriterion =
                     (IcmpTypeCriterion) criterion;
             return root.put("icmpType", icmpTypeCriterion.icmpType());
@@ -252,7 +252,7 @@
 
     private static class FormatIcmpV4Code implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final IcmpCodeCriterion icmpCodeCriterion =
                     (IcmpCodeCriterion) criterion;
             return root.put("icmpCode", icmpCodeCriterion.icmpCode());
@@ -261,7 +261,7 @@
 
     private static class FormatIpV6FLabel implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final IPv6FlowLabelCriterion ipv6FlowLabelCriterion =
                     (IPv6FlowLabelCriterion) criterion;
             return root.put("flowLabel", ipv6FlowLabelCriterion.flowLabel());
@@ -270,7 +270,7 @@
 
     private static class FormatIcmpV6Type implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final Icmpv6TypeCriterion icmpv6TypeCriterion =
                     (Icmpv6TypeCriterion) criterion;
             return root.put("icmpv6Type", icmpv6TypeCriterion.icmpv6Type());
@@ -279,7 +279,7 @@
 
     private static class FormatIcmpV6Code implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final Icmpv6CodeCriterion icmpv6CodeCriterion =
                     (Icmpv6CodeCriterion) criterion;
             return root.put("icmpv6Code", icmpv6CodeCriterion.icmpv6Code());
@@ -288,7 +288,7 @@
 
     private static class FormatV6NDTarget implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final IPv6NDTargetAddressCriterion ipv6NDTargetAddressCriterion
                 = (IPv6NDTargetAddressCriterion) criterion;
             return root.put("targetAddress", ipv6NDTargetAddressCriterion.targetAddress().toString());
@@ -297,7 +297,7 @@
 
     private static class FormatV6NDTll implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final IPv6NDLinkLayerAddressCriterion ipv6NDLinkLayerAddressCriterion
                 = (IPv6NDLinkLayerAddressCriterion) criterion;
             return root.put("mac", ipv6NDLinkLayerAddressCriterion.mac().toString());
@@ -306,7 +306,7 @@
 
     private static class FormatMplsLabel implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final MplsCriterion mplsCriterion =
                     (MplsCriterion) criterion;
             return root.put("label", mplsCriterion.label().toInt());
@@ -315,7 +315,7 @@
 
     private static class FormatIpV6Exthdr implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final IPv6ExthdrFlagsCriterion exthdrCriterion =
                     (IPv6ExthdrFlagsCriterion) criterion;
             return root.put("exthdrFlags", exthdrCriterion.exthdrFlags());
@@ -324,7 +324,7 @@
 
     private static class FormatOchSigId implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final LambdaCriterion lambdaCriterion =
                     (LambdaCriterion) criterion;
             return root.put("lambda", lambdaCriterion.lambda());
@@ -333,7 +333,7 @@
 
     private static class FormatOchSigType implements CriterionTypeFormatter {
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             final OpticalSignalTypeCriterion opticalSignalTypeCriterion =
                     (OpticalSignalTypeCriterion) criterion;
             return root.put("signalType", opticalSignalTypeCriterion.signalType());
@@ -343,7 +343,7 @@
     private class FormatDummyType implements CriterionTypeFormatter {
 
         @Override
-        public ObjectNode formatCriterion(ObjectNode root, Criterion criterion) {
+        public ObjectNode encodeCriterion(ObjectNode root, Criterion criterion) {
             checkNotNull(criterion, "Criterion cannot be null");
 
             return root.put("type", criterion.type().toString());
@@ -364,7 +364,7 @@
                         "No formatter found for criterion type "
                                 + criterion.type().toString());
 
-        return formatter.formatCriterion(result, criterion);
+        return formatter.encodeCriterion(result, criterion);
     }
 
 
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/DeviceCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/DeviceCodec.java
index 7f78756..f1a4f78 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/DeviceCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/DeviceCodec.java
@@ -48,7 +48,7 @@
     @Override
     public ObjectNode encode(Device device, CodecContext context) {
         checkNotNull(device, "Device cannot be null");
-        DeviceService service = context.get(DeviceService.class);
+        DeviceService service = context.getService(DeviceService.class);
         ObjectNode result = context.mapper().createObjectNode()
                 .put(ID, device.id().toString())
                 .put(TYPE, device.type().name())
diff --git a/core/common/src/main/java/org/onosproject/codec/impl/LinkCodec.java b/core/common/src/main/java/org/onosproject/codec/impl/LinkCodec.java
index 65fcb80..491d751 100644
--- a/core/common/src/main/java/org/onosproject/codec/impl/LinkCodec.java
+++ b/core/common/src/main/java/org/onosproject/codec/impl/LinkCodec.java
@@ -37,6 +37,7 @@
     private static final String SRC = "src";
     private static final String DST = "dst";
     private static final String TYPE = "type";
+    private static final String STATE = "state";
 
     @Override
     public ObjectNode encode(Link link, CodecContext context) {
@@ -46,6 +47,9 @@
         result.set(SRC, codec.encode(link.src(), context));
         result.set(DST, codec.encode(link.dst(), context));
         result.put(TYPE, link.type().toString());
+        if (link.state() != null) {
+            result.put(STATE, link.state().toString());
+        }
         return annotate(result, link, context);
     }
 
diff --git a/core/common/src/test/java/org/onosproject/codec/impl/MockCodecContext.java b/core/common/src/test/java/org/onosproject/codec/impl/MockCodecContext.java
index 4c869c1..6a9b670 100644
--- a/core/common/src/test/java/org/onosproject/codec/impl/MockCodecContext.java
+++ b/core/common/src/test/java/org/onosproject/codec/impl/MockCodecContext.java
@@ -52,7 +52,7 @@
 
     @SuppressWarnings("unchecked")
     @Override
-    public <T> T get(Class<T> serviceClass) {
+    public <T> T getService(Class<T> serviceClass) {
         return (T) services.get(serviceClass);
     }
 
diff --git a/web/api/src/test/java/org/onosproject/rest/ApplicationsResourceTest.java b/web/api/src/test/java/org/onosproject/rest/ApplicationsResourceTest.java
index 81db631..949dbe8 100644
--- a/web/api/src/test/java/org/onosproject/rest/ApplicationsResourceTest.java
+++ b/web/api/src/test/java/org/onosproject/rest/ApplicationsResourceTest.java
@@ -67,7 +67,7 @@
 
         @Override
         @SuppressWarnings("unchecked")
-        public <T> T get(Class<T> serviceClass) {
+        public <T> T getService(Class<T> serviceClass) {
             return (T) service;
         }
     }