diff --git a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentInstaller.java b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentInstaller.java
index 772ab7a..a612f21 100644
--- a/core/net/src/main/java/org/onosproject/net/intent/impl/IntentInstaller.java
+++ b/core/net/src/main/java/org/onosproject/net/intent/impl/IntentInstaller.java
@@ -16,23 +16,32 @@
 
 package org.onosproject.net.intent.impl;
 
+import com.google.common.collect.Sets;
+import org.onosproject.net.DeviceId;
 import org.onosproject.net.flow.FlowRule;
 import org.onosproject.net.flow.FlowRuleOperations;
 import org.onosproject.net.flow.FlowRuleOperationsContext;
 import org.onosproject.net.flow.FlowRuleService;
 import org.onosproject.net.flowobjective.FlowObjectiveService;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.flowobjective.ObjectiveContext;
+import org.onosproject.net.flowobjective.ObjectiveError;
+import org.onosproject.net.intent.FlowObjectiveIntent;
 import org.onosproject.net.intent.FlowRuleIntent;
 import org.onosproject.net.intent.Intent;
 import org.onosproject.net.intent.IntentData;
 import org.onosproject.net.intent.IntentStore;
 import org.slf4j.Logger;
 
+import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Optional;
 import java.util.Set;
+import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
+import static com.google.common.base.Preconditions.checkState;
 import static org.onosproject.net.intent.IntentState.*;
 import static org.slf4j.LoggerFactory.getLogger;
 
@@ -69,51 +78,10 @@
         this.flowObjectiveService = flowObjectiveService;
     }
 
-    private void applyIntentData(Optional<IntentData> intentData,
-                                 FlowRuleOperations.Builder builder,
-                                 Direction direction) {
-        if (!intentData.isPresent()) {
-            return;
-        }
-        IntentData data = intentData.get();
-
-        List<Intent> intentsToApply = data.installables();
-        if (!intentsToApply.stream().allMatch(x -> x instanceof FlowRuleIntent)) {
-            throw new IllegalStateException("installable intents must be FlowRuleIntent");
-        }
-
-        if (direction == Direction.ADD) {
-            trackerService.addTrackedResources(data.key(), data.intent().resources());
-            intentsToApply.forEach(installable ->
-                                           trackerService.addTrackedResources(data.key(), installable.resources()));
-        } else {
-            trackerService.removeTrackedResources(data.key(), data.intent().resources());
-            intentsToApply.forEach(installable ->
-                                           trackerService.removeTrackedResources(data.intent().key(),
-                                                                                 installable.resources()));
-        }
-
-        // FIXME do FlowRuleIntents have stages??? Can we do uninstall work in parallel? I think so.
-        builder.newStage();
-
-        List<Collection<FlowRule>> stages = intentsToApply.stream()
-                .map(x -> (FlowRuleIntent) x)
-                .map(FlowRuleIntent::flowRules)
-                .collect(Collectors.toList());
-
-        for (Collection<FlowRule> rules : stages) {
-            if (direction == Direction.ADD) {
-                rules.forEach(builder::add);
-            } else {
-                rules.forEach(builder::remove);
-            }
-        }
-
-    }
 
     // FIXME: Refactor to accept both FlowObjectiveIntent and FlowRuleIntents
-    // Note: Intent Manager should have never become dependent on a specific
-    // intent type.
+    // FIXME: Intent Manager should have never become dependent on a specific intent type(s).
+    // This will be addressed in intent domains work; not now.
 
     /**
      * Applies the specified intent updates to the environment by uninstalling
@@ -123,67 +91,319 @@
      * @param toInstall   optional intent to install
      */
     void apply(Optional<IntentData> toUninstall, Optional<IntentData> toInstall) {
-        // need to consider if FlowRuleIntent is only one as installable intent or not
-
-        FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
-        applyIntentData(toUninstall, builder, Direction.REMOVE);
-        applyIntentData(toInstall, builder, Direction.ADD);
-
-        FlowRuleOperations operations = builder.build(new FlowRuleOperationsContext() {
-            @Override
-            public void onSuccess(FlowRuleOperations ops) {
-                if (toInstall.isPresent()) {
-                    IntentData installData = toInstall.get();
-                    log.debug("Completed installing: {}", installData.key());
-                    installData.setState(INSTALLED);
-                    store.write(installData);
-                } else if (toUninstall.isPresent()) {
-                    IntentData uninstallData = toUninstall.get();
-                    log.debug("Completed withdrawing: {}", uninstallData.key());
-                    switch (uninstallData.request()) {
-                        case INSTALL_REQ:
-                            uninstallData.setState(FAILED);
-                            break;
-                        case WITHDRAW_REQ:
-                        default: //TODO "default" case should not happen
-                            uninstallData.setState(WITHDRAWN);
-                            break;
-                    }
-                    store.write(uninstallData);
+        // Hook for handling success
+        Consumer<OperationContext> successConsumer = (ctx) -> {
+            if (toInstall.isPresent()) {
+                IntentData installData = toInstall.get();
+                log.debug("Completed installing: {}", installData.key());
+                installData.setState(INSTALLED);
+                store.write(installData);
+            } else if (toUninstall.isPresent()) {
+                IntentData uninstallData = toUninstall.get();
+                log.debug("Completed withdrawing: {}", uninstallData.key());
+                switch (uninstallData.request()) {
+                    case INSTALL_REQ:
+                        uninstallData.setState(FAILED);
+                        break;
+                    case WITHDRAW_REQ:
+                    default: //TODO "default" case should not happen
+                        uninstallData.setState(WITHDRAWN);
+                        break;
                 }
+                store.write(uninstallData);
             }
+        };
 
-            @Override
-            public void onError(FlowRuleOperations ops) {
-                // if toInstall was cause of error, then recompile (manage/increment counter, when exceeded -> CORRUPT)
-                if (toInstall.isPresent()) {
-                    IntentData installData = toInstall.get();
-                    log.warn("Failed installation: {} {} on {}",
-                             installData.key(), installData.intent(), ops);
-                    installData.setState(CORRUPT);
-                    installData.incrementErrorCount();
-                    store.write(installData);
-                }
-                // if toUninstall was cause of error, then CORRUPT (another job will clean this up)
-                if (toUninstall.isPresent()) {
-                    IntentData uninstallData = toUninstall.get();
-                    log.warn("Failed withdrawal: {} {} on {}",
-                             uninstallData.key(), uninstallData.intent(), ops);
-                    uninstallData.setState(CORRUPT);
-                    uninstallData.incrementErrorCount();
-                    store.write(uninstallData);
-                }
+        // Hook for handling errors
+        Consumer<OperationContext> errorConsumer = (ctx) -> {
+            // if toInstall was cause of error, then recompile (manage/increment counter, when exceeded -> CORRUPT)
+            if (toInstall.isPresent()) {
+                IntentData installData = toInstall.get();
+                log.warn("Failed installation: {} {} on {}",
+                         installData.key(), installData.intent(), ctx.error());
+                installData.setState(CORRUPT);
+                installData.incrementErrorCount();
+                store.write(installData);
             }
-        });
+            // if toUninstall was cause of error, then CORRUPT (another job will clean this up)
+            if (toUninstall.isPresent()) {
+                IntentData uninstallData = toUninstall.get();
+                log.warn("Failed withdrawal: {} {} on {}",
+                         uninstallData.key(), uninstallData.intent(), ctx.error());
+                uninstallData.setState(CORRUPT);
+                uninstallData.incrementErrorCount();
+                store.write(uninstallData);
+            }
+        };
 
-        if (log.isTraceEnabled()) {
-            log.trace("applying intent {} -> {} with {} rules: {}",
-                      toUninstall.map(x -> x.key().toString()).orElse("<empty>"),
-                      toInstall.map(x -> x.key().toString()).orElse("<empty>"),
-                      operations.stages().stream().mapToLong(Set::size).sum(),
-                      operations.stages());
+        // Create a context for tracking the backing operations for applying
+        // the intents to the environment.
+        OperationContext context = createContext(toUninstall, toInstall);
+
+        context.prepare(toUninstall, toInstall, successConsumer, errorConsumer);
+        context.apply();
+    }
+
+    // ------ Utilities to support FlowRule vs. FlowObjective behavior -------
+
+    // Creates the context appropriate for tracking operations of the
+    // the specified intents.
+    private OperationContext createContext(Optional<IntentData> toUninstall,
+                                           Optional<IntentData> toInstall) {
+        if (isInstallable(toUninstall, toInstall, FlowRuleIntent.class)) {
+            return new FlowRuleOperationContext();
+        }
+        if (isInstallable(toUninstall, toInstall, FlowObjectiveIntent.class)) {
+            return new FlowObjectiveOperationContext();
+        }
+        return new ErrorContext();
+    }
+
+    private boolean isInstallable(Optional<IntentData> toUninstall, Optional<IntentData> toInstall,
+                                  Class<? extends Intent> intentClass) {
+        boolean notBothNull = false;
+        if (toInstall.isPresent()) {
+            notBothNull = true;
+            if (!toInstall.get().installables().stream()
+                    .allMatch(i -> intentClass.isAssignableFrom(i.getClass()))) {
+                return false;
+            }
+        }
+        if (toUninstall.isPresent()) {
+            notBothNull = true;
+            if (!toUninstall.get().installables().stream()
+                    .allMatch(i -> intentClass.isAssignableFrom(i.getClass()))) {
+                return false;
+            }
+        }
+        return notBothNull;
+    }
+
+    // Base context for applying and tracking operations related to installable intents.
+    private abstract class OperationContext {
+        protected Optional<IntentData> toUninstall;
+        protected Optional<IntentData> toInstall;
+        protected Consumer<OperationContext> successConsumer;
+        protected Consumer<OperationContext> errorConsumer;
+
+        abstract void apply();
+
+        abstract Object error();
+
+        abstract void prepareIntents(List<Intent> intentsToApply, Direction direction);
+
+        void prepare(Optional<IntentData> toUninstall, Optional<IntentData> toInstall,
+                     Consumer<OperationContext> successConsumer,
+                     Consumer<OperationContext> errorConsumer) {
+            this.toUninstall = toUninstall;
+            this.toInstall = toInstall;
+            this.successConsumer = successConsumer;
+            this.errorConsumer = errorConsumer;
+            prepareIntentData(toUninstall, Direction.REMOVE);
+            prepareIntentData(toInstall, Direction.ADD);
         }
 
-        flowRuleService.apply(operations);
+        /**
+         * Applies the specified intent data, if present, to the network using the
+         * specified context.
+         *
+         * @param intentData optional intent data; no-op if not present
+         * @param direction  indicates adding or removal
+         */
+        private void prepareIntentData(Optional<IntentData> intentData, Direction direction) {
+            if (!intentData.isPresent()) {
+                return;
+            }
+
+            IntentData data = intentData.get();
+            List<Intent> intentsToApply = data.installables();
+            checkState(intentsToApply.stream().allMatch(this::isSupported),
+                       "Unsupported installable intents detected");
+
+            if (direction == Direction.ADD) {
+                trackerService.addTrackedResources(data.key(), data.intent().resources());
+                intentsToApply.forEach(installable ->
+                                               trackerService.addTrackedResources(data.key(),
+                                                                                  installable.resources()));
+            } else {
+                trackerService.removeTrackedResources(data.key(), data.intent().resources());
+                intentsToApply.forEach(installable ->
+                                               trackerService.removeTrackedResources(data.intent().key(),
+                                                                                     installable.resources()));
+            }
+
+            prepareIntents(intentsToApply, direction);
+        }
+
+        private boolean isSupported(Intent intent) {
+            return intent instanceof FlowRuleIntent || intent instanceof FlowObjectiveIntent;
+        }
+    }
+
+
+    // Context for applying and tracking operations related to flow rule intent.
+    private class FlowRuleOperationContext extends OperationContext {
+        FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
+        FlowRuleOperationsContext flowRuleOperationsContext;
+
+        void apply() {
+            flowRuleOperationsContext = new FlowRuleOperationsContext() {
+                @Override
+                public void onSuccess(FlowRuleOperations ops) {
+                    successConsumer.accept(FlowRuleOperationContext.this);
+                }
+
+                @Override
+                public void onError(FlowRuleOperations ops) {
+                    errorConsumer.accept(FlowRuleOperationContext.this);
+                }
+            };
+            FlowRuleOperations operations = builder.build(flowRuleOperationsContext);
+
+            if (log.isTraceEnabled()) {
+                log.trace("applying intent {} -> {} with {} rules: {}",
+                          toUninstall.map(x -> x.key().toString()).orElse("<empty>"),
+                          toInstall.map(x -> x.key().toString()).orElse("<empty>"),
+                          operations.stages().stream().mapToLong(Set::size).sum(),
+                          operations.stages());
+            }
+
+            flowRuleService.apply(operations);
+        }
+
+        @Override
+        public void prepareIntents(List<Intent> intentsToApply, Direction direction) {
+            // FIXME do FlowRuleIntents have stages??? Can we do uninstall work in parallel? I think so.
+            builder.newStage();
+
+            List<Collection<FlowRule>> stages = intentsToApply.stream()
+                    .map(x -> (FlowRuleIntent) x)
+                    .map(FlowRuleIntent::flowRules)
+                    .collect(Collectors.toList());
+
+            for (Collection<FlowRule> rules : stages) {
+                if (direction == Direction.ADD) {
+                    rules.forEach(builder::add);
+                } else {
+                    rules.forEach(builder::remove);
+                }
+            }
+
+        }
+
+        @Override
+        public Object error() {
+            return flowRuleOperationsContext;
+        }
+    }
+
+    // Context for applying and tracking operations related to flow objective intents.
+    private class FlowObjectiveOperationContext extends OperationContext {
+        List<FlowObjectiveInstallationContext> contexts;
+        final Set<ObjectiveContext> pendingContexts = Sets.newHashSet();
+        final Set<ObjectiveContext> errorContexts = Sets.newConcurrentHashSet();
+
+        @Override
+        public void prepareIntents(List<Intent> intentsToApply, Direction direction) {
+            contexts = intentsToApply.stream()
+                    .flatMap(x -> buildObjectiveContexts((FlowObjectiveIntent) x, direction).stream())
+                    .collect(Collectors.toList());
+        }
+
+        // Builds the specified objective in the appropriate direction
+        private List<FlowObjectiveInstallationContext> buildObjectiveContexts(FlowObjectiveIntent intent,
+                                                                              Direction direction) {
+            int size = intent.objectives().size();
+            List<FlowObjectiveInstallationContext> contexts = new ArrayList<>(size);
+            for (int i = 0; i < size; i++) {
+                DeviceId deviceId = intent.devices().get(i);
+                Objective.Builder builder = intent.objectives().get(i).copy();
+                FlowObjectiveInstallationContext context = new FlowObjectiveInstallationContext();
+
+                final Objective objective;
+                switch (direction) {
+                    case ADD:
+                        objective = builder.add(context);
+                        break;
+                    case REMOVE:
+                        objective = builder.remove(context);
+                        break;
+                    default:
+                        throw new UnsupportedOperationException("Unsupported direction " + direction);
+                }
+                context.setObjective(objective, deviceId);
+                contexts.add(context);
+            }
+            return contexts;
+        }
+
+        @Override
+        void apply() {
+            contexts.forEach(objectiveContext -> {
+                pendingContexts.add(objectiveContext);
+                flowObjectiveService.apply(objectiveContext.deviceId,
+                                           objectiveContext.objective);
+            });
+        }
+
+        @Override
+        public Object error() {
+            return errorContexts;
+        }
+
+        private class FlowObjectiveInstallationContext implements ObjectiveContext {
+            Objective objective;
+            DeviceId deviceId;
+
+            void setObjective(Objective objective, DeviceId deviceId) {
+                this.objective = objective;
+                this.deviceId = deviceId;
+            }
+
+            @Override
+            public void onSuccess(Objective objective) {
+                finish();
+            }
+
+            @Override
+            public void onError(Objective objective, ObjectiveError error) {
+                errorContexts.add(this);
+                finish();
+            }
+
+            private void finish() {
+                synchronized (pendingContexts) {
+                    pendingContexts.remove(this);
+                    if (pendingContexts.isEmpty()) {
+                        if (errorContexts.isEmpty()) {
+                            successConsumer.accept(FlowObjectiveOperationContext.this);
+                        } else {
+                            errorConsumer.accept(FlowObjectiveOperationContext.this);
+                        }
+                    }
+                }
+            }
+
+            @Override
+            public String toString() {
+                return String.format("(%s, %s)", deviceId, objective);
+            }
+        }
+    }
+
+    private class ErrorContext extends OperationContext {
+        @Override
+        void apply() {
+            throw new UnsupportedOperationException("Unsupported installable intent");
+        }
+
+        @Override
+        Object error() {
+            return null;
+        }
+
+        @Override
+        void prepareIntents(List<Intent> intentsToApply, Direction direction) {
+        }
     }
 }
