You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by or...@apache.org on 2018/12/18 18:23:55 UTC

[qpid-broker-j] 03/03: QPID-6948: [Broker-J] Add compatibility layer for REST API v6.1

This is an automated email from the ASF dual-hosted git repository.

orudyy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git

commit f4807cbd0297203c322deb54ce02b2c54e19cf44
Author: Alex Rudyy <or...@apache.org>
AuthorDate: Tue Dec 18 17:20:22 2018 +0000

    QPID-6948: [Broker-J] Add compatibility layer for REST API v6.1
---
 .../v6_1/LegacyManagementController.java           | 194 +++++++
 .../v6_1/LegacyManagementControllerFactory.java    |  61 ++
 .../v6_1/category/BindingController.java           | 611 +++++++++++++++++++++
 .../controller/v6_1/category/BrokerController.java | 212 +++++++
 .../v6_1/category/ConsumerController.java          | 257 +++++++++
 .../v6_1/category/DestinationController.java       | 207 +++++++
 .../v6_1/category/ExchangeController.java          |  92 ++++
 .../v6_1/category/LegacyCategoryController.java    |  62 +++
 .../category/LegacyCategoryControllerFactory.java  | 268 +++++++++
 .../controller/v6_1/category/PortController.java   | 140 +++++
 .../controller/v6_1/category/QueueController.java  | 273 +++++++++
 .../v6_1/category/SessionController.java           | 111 ++++
 .../v6_1/category/VirtualHostController.java       | 130 +++++
 .../v6_1/LegacyManagementControllerTest.java       | 138 +++++
 .../v6_1/category/BindingControllerTest.java       | 312 +++++++++++
 .../v6_1/category/BrokerControllerTest.java        | 104 ++++
 .../v6_1/category/ConsumerControllerTest.java      | 317 +++++++++++
 .../v6_1/category/DestinationControllerTest.java   | 135 +++++
 .../v6_1/category/ExchangeControllerTest.java      | 113 ++++
 .../LegacyCategoryControllerFactoryTest.java       |  63 +++
 .../category/LegacyCategoryControllerTest.java     |  80 +++
 .../v6_1/category/PortControllerTest.java          | 113 ++++
 .../v6_1/category/QueueControllerTest.java         | 161 ++++++
 .../v6_1/category/SessionControllerTest.java       |  95 ++++
 .../v6_1/category/VirtualHostControllerTest.java   | 104 ++++
 25 files changed, 4353 insertions(+)

diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/LegacyManagementController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/LegacyManagementController.java
new file mode 100644
index 0000000..773db9d
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/LegacyManagementController.java
@@ -0,0 +1,194 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1;
+
+import static org.apache.qpid.server.management.plugin.ManagementException.createUnprocessableManagementException;
+import static org.apache.qpid.server.management.plugin.controller.ConverterHelper.getIntParameterFromRequest;
+import static org.apache.qpid.server.management.plugin.controller.ConverterHelper.getParameter;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.ManagementException;
+import org.apache.qpid.server.management.plugin.controller.AbstractLegacyConfiguredObjectController;
+import org.apache.qpid.server.management.plugin.controller.ConverterHelper;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.model.ConfiguredObject;
+
+public class LegacyManagementController extends AbstractLegacyConfiguredObjectController
+{
+    private static final String DEPTH_PARAM = "depth";
+    private static final String OVERSIZE_PARAM = "oversize";
+    private static final String ACTUALS_PARAM = "actuals";
+    private static final String INCLUDE_SYS_CONTEXT_PARAM = "includeSysContext";
+    private static final String INHERITED_ACTUALS_PARAM = "inheritedActuals";
+    private static final String EXCLUDE_INHERITED_CONTEXT_PARAM = "excludeInheritedContext";
+
+
+    private static final int DEFAULT_DEPTH = 1;
+    private static final int DEFAULT_OVERSIZE = 120;
+
+    LegacyManagementController(final ManagementController nextVersionManagementController)
+    {
+        super(LegacyManagementControllerFactory.MODEL_VERSION, nextVersionManagementController);
+    }
+
+    @Override
+    public Object get(final ConfiguredObject<?> root,
+                      final String category,
+                      final List<String> path,
+                      final Map<String, List<String>> parameters) throws ManagementException
+    {
+        Object result = super.get(root, category, path, convertQueryParameters(parameters));
+        if (result instanceof LegacyConfiguredObject)
+        {
+            return Collections.singletonList(result);
+        }
+        return result;
+    }
+
+
+    @Override
+    public Map<String, List<String>> convertQueryParameters(final Map<String, List<String>> requestParameters)
+    {
+        Map<String, List<String>> params = requestParameters
+                .entrySet()
+                .stream()
+                .filter(e -> !INCLUDE_SYS_CONTEXT_PARAM.equals(e.getKey())
+                             && !INHERITED_ACTUALS_PARAM.equals(e.getKey()))
+                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
+        Map<String, List<String>> parameters = new HashMap<>(params);
+        boolean excludeInheritedContext = isInheritedContextExcluded(params);
+        parameters.put(EXCLUDE_INHERITED_CONTEXT_PARAM,
+                       Collections.singletonList(String.valueOf(excludeInheritedContext)));
+        if (!parameters.containsKey(DEPTH_PARAM))
+        {
+            parameters.put(DEPTH_PARAM, Collections.singletonList("1"));
+        }
+        return parameters;
+    }
+
+    @Override
+    public Object formatConfiguredObject(final Object content,
+                                         final Map<String, List<String>> parameters,
+                                         final boolean isSecureOrAllowedOnInsecureChannel)
+    {
+        final int depth = getIntParameterFromRequest(parameters, DEPTH_PARAM, DEFAULT_DEPTH);
+        final int oversizeThreshold = getIntParameterFromRequest(parameters, OVERSIZE_PARAM, DEFAULT_OVERSIZE);
+        final boolean actuals = Boolean.parseBoolean(getParameter(ACTUALS_PARAM, parameters));
+        final boolean excludeInheritedContext = isInheritedContextExcluded(parameters);
+
+        if (content instanceof LegacyConfiguredObject)
+        {
+            LegacyConfiguredObject legacyConfiguredObjectObject = (LegacyConfiguredObject) content;
+            return convertManageableToMap(
+                    legacyConfiguredObjectObject,
+                    depth,
+                    actuals,
+                    oversizeThreshold,
+                    excludeInheritedContext);
+        }
+        else if (content instanceof Collection)
+        {
+            return ((Collection<?>) content).stream()
+                                            .filter(o -> o instanceof LegacyConfiguredObject)
+                                            .map(LegacyConfiguredObject.class::cast)
+                                            .map(o -> convertManageableToMap(
+                                                    o,
+                                                    depth,
+                                                    actuals,
+                                                    oversizeThreshold,
+                                                    excludeInheritedContext))
+                                            .collect(Collectors.toSet());
+        }
+        return content;
+    }
+
+
+    private Map<String, Object> convertManageableToMap(final LegacyConfiguredObject legacyConfiguredObjectObject,
+                                                       final int depth,
+                                                       final boolean actuals,
+                                                       final int oversizeThreshold,
+                                                       final boolean excludeInheritedContext)
+    {
+        return convertObject(legacyConfiguredObjectObject,
+                             depth,
+                             actuals,
+                             oversizeThreshold,
+                             true,
+                             excludeInheritedContext);
+    }
+
+
+    private boolean isInheritedContextExcluded(final Map<String, List<String>> params)
+    {
+        boolean excludeInheritedContext;
+        boolean actuals = Boolean.parseBoolean(ConverterHelper.getParameter(ACTUALS_PARAM, params));
+        String includeSystemContextParameter = ConverterHelper.getParameter(INCLUDE_SYS_CONTEXT_PARAM, params);
+        String inheritedActualsParameter = ConverterHelper.getParameter(INHERITED_ACTUALS_PARAM, params);
+        String excludeInheritedContextParameter =
+                ConverterHelper.getParameter(EXCLUDE_INHERITED_CONTEXT_PARAM, params);
+        if (excludeInheritedContextParameter == null)
+        {
+            if (inheritedActualsParameter == null && includeSystemContextParameter == null)
+            {
+                excludeInheritedContext = actuals;
+            }
+            else if (inheritedActualsParameter != null && includeSystemContextParameter != null)
+            {
+                if (actuals)
+                {
+                    excludeInheritedContext = !Boolean.parseBoolean(inheritedActualsParameter);
+                }
+                else
+                {
+                    excludeInheritedContext = !Boolean.parseBoolean(includeSystemContextParameter);
+                }
+            }
+            else if (inheritedActualsParameter != null)
+            {
+                excludeInheritedContext = actuals && !Boolean.parseBoolean(inheritedActualsParameter);
+            }
+            else
+            {
+                excludeInheritedContext = actuals || !Boolean.parseBoolean(includeSystemContextParameter);
+            }
+        }
+        else
+        {
+            if (inheritedActualsParameter != null || includeSystemContextParameter != null)
+            {
+                throw createUnprocessableManagementException(String.format(
+                        "Parameter '%s' cannot be specified together with '%s' or '%s'",
+                        EXCLUDE_INHERITED_CONTEXT_PARAM,
+                        INHERITED_ACTUALS_PARAM,
+                        INCLUDE_SYS_CONTEXT_PARAM));
+            }
+            excludeInheritedContext = Boolean.parseBoolean(excludeInheritedContextParameter);
+        }
+        return excludeInheritedContext;
+    }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/LegacyManagementControllerFactory.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/LegacyManagementControllerFactory.java
new file mode 100644
index 0000000..d625b48
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/LegacyManagementControllerFactory.java
@@ -0,0 +1,61 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1;
+
+import org.apache.qpid.server.management.plugin.HttpManagementConfiguration;
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.ManagementControllerFactory;
+import org.apache.qpid.server.management.plugin.controller.CategoryControllerFactory;
+import org.apache.qpid.server.management.plugin.controller.TypeControllerFactory;
+import org.apache.qpid.server.plugin.PluggableService;
+
+@PluggableService
+public class LegacyManagementControllerFactory implements ManagementControllerFactory
+{
+    public static final String MODEL_VERSION = "6.1";
+
+    @Override
+    public String getType()
+    {
+        return "org.apache.qpid.server.management.plugin.model.v6_1";
+    }
+
+    @Override
+    public String getVersion()
+    {
+        return MODEL_VERSION;
+    }
+
+    @Override
+    public String getPreviousVersion()
+    {
+        return "6.0";
+    }
+
+    @Override
+    public ManagementController createManagementController(final HttpManagementConfiguration<?> httpManagement,
+                                                           final ManagementController nextVersionManagementController)
+    {
+        final LegacyManagementController controller = new LegacyManagementController(nextVersionManagementController);
+        controller.initialize();
+        return controller;
+    }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/BindingController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/BindingController.java
new file mode 100644
index 0000000..a117d96
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/BindingController.java
@@ -0,0 +1,611 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import static org.apache.qpid.server.management.plugin.ManagementException.createBadRequestManagementException;
+import static org.apache.qpid.server.management.plugin.ManagementException.createInternalServerErrorManagementException;
+
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.ManagementException;
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.management.plugin.ResponseType;
+import org.apache.qpid.server.management.plugin.controller.CategoryController;
+import org.apache.qpid.server.management.plugin.controller.ControllerManagementResponse;
+import org.apache.qpid.server.management.plugin.controller.GenericLegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.State;
+
+public class BindingController implements CategoryController
+{
+    public static final String TYPE = "Binding";
+    private final LegacyManagementController _managementController;
+    private final ManagementController _nextVersionManagementController;
+
+    BindingController(final LegacyManagementController managementController)
+    {
+        _managementController = managementController;
+        _nextVersionManagementController = _managementController.getNextVersionManagementController();
+    }
+
+    @Override
+    public String getCategory()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public String getNextVersionCategory()
+    {
+        return null;
+    }
+
+    @Override
+    public String getDefaultType()
+    {
+        return null;
+    }
+
+    @Override
+    public String[] getParentCategories()
+    {
+        return new String[]{ExchangeController.TYPE, QueueController.TYPE};
+    }
+
+    @Override
+    public LegacyManagementController getManagementController()
+    {
+        return _managementController;
+    }
+
+    @Override
+    public Object get(final ConfiguredObject<?> root,
+                      final List<String> path,
+                      final Map<String, List<String>> parameters) throws ManagementException
+    {
+        final Collection<String> hierarchy = _managementController.getCategoryHierarchy(root, getCategory());
+
+        final String bindingName = path.size() == hierarchy.size() ? path.get(hierarchy.size() - 1) : null;
+        final String queueName = path.size() >= hierarchy.size() - 1 ? path.get(hierarchy.size() - 2) : null;
+
+        final List<String> exchangePath =
+                path.size() >= hierarchy.size() - 2 ? path.subList(0, hierarchy.size() - 2) : path;
+
+        return getExchangeBindings(root, exchangePath, queueName, bindingName);
+
+    }
+
+
+    @Override
+    public LegacyConfiguredObject createOrUpdate(final ConfiguredObject<?> root,
+                                                 final List<String> path,
+                                                 final Map<String, Object> attributes,
+                                                 final boolean isPost) throws ManagementException
+    {
+        if (path.contains("*"))
+        {
+            throw createBadRequestManagementException("Wildcards in path are not supported for post and put requests");
+        }
+
+        final Collection<String> hierarchy = _managementController.getCategoryHierarchy(root, getCategory());
+        if (path.size() < hierarchy.size() - 2)
+        {
+            throw createBadRequestManagementException(String.format("Cannot create binding for path %s",
+                                                                    String.join("/" + path)));
+        }
+
+        String queueName = null;
+
+        if (path.size() > hierarchy.size() - 2)
+        {
+            queueName = path.get(hierarchy.size() - 2);
+        }
+        if (queueName == null)
+        {
+            queueName = (String) attributes.get("queue");
+        }
+        if (queueName == null)
+        {
+            throw createBadRequestManagementException(
+                    "Queue is required for binding creation. Please specify queue either in path or in binding attributes");
+        }
+
+        final List<String> exchangePath = path.subList(0, hierarchy.size() - 3);
+        final LegacyConfiguredObject
+                nextVersionExchange = getNextVersionObject(root, exchangePath, ExchangeController.TYPE);
+        final List<String> queuePath = new ArrayList<>(path.subList(0, hierarchy.size() - 4));
+        queuePath.add(queueName);
+        final LegacyConfiguredObject nextVersionQueue =
+                getNextVersionObject(root, queuePath, QueueController.TYPE);
+
+        String bindingKey = (String) attributes.get(GenericLegacyConfiguredObject.NAME);
+        if (bindingKey == null)
+        {
+            bindingKey = path.size() == hierarchy.size() ? path.get(hierarchy.size() - 1) : null;
+        }
+        if (bindingKey == null)
+        {
+            bindingKey = "";
+        }
+
+        final Map<String, Object> parameters = new LinkedHashMap<>();
+        parameters.put("bindingKey", bindingKey);
+        parameters.put("destination", queueName);
+
+        Map<String, Object> arguments = null;
+        if (attributes.containsKey("arguments"))
+        {
+            Object args = attributes.get("arguments");
+            if (args instanceof Map)
+            {
+                @SuppressWarnings("unchecked")
+                Map<String, Object> argumentsMap = (Map<String, Object>) args;
+                arguments = new HashMap<>(argumentsMap);
+                if (!arguments.isEmpty())
+                {
+                    parameters.put("arguments", arguments);
+                }
+            }
+            else
+            {
+                throw createBadRequestManagementException(String.format("Unexpected attributes specified : %s", args));
+            }
+        }
+        parameters.put("replaceExistingArguments", !isPost);
+
+        ManagementResponse response = nextVersionExchange.invoke("bind", parameters, true);
+        final boolean newBindings = Boolean.TRUE.equals(response.getBody());
+        if (!newBindings)
+        {
+            return null;
+        }
+
+        return new LegacyBinding(_managementController,
+                                 nextVersionExchange,
+                                 nextVersionQueue,
+                                 bindingKey,
+                                 arguments);
+    }
+
+    @Override
+    public int delete(final ConfiguredObject<?> root,
+                      final List<String> path,
+                      final Map<String, List<String>> parameters) throws ManagementException
+    {
+        if (path.contains("*"))
+        {
+            throw createBadRequestManagementException("Wildcards in path are not supported for delete requests");
+        }
+
+        final Collection<String> hierarchy = _managementController.getCategoryHierarchy(root, getCategory());
+        if (path.size() < hierarchy.size() - 2)
+        {
+            throw createBadRequestManagementException(String.format("Cannot delete binding for path %s",
+                                                                    String.join("/", path)));
+        }
+
+        final String bindingName = path.size() == hierarchy.size() ? path.get(hierarchy.size() - 1) : null;
+        final String queueName = path.get(hierarchy.size() - 2);
+        final List<String> ids = parameters.get(GenericLegacyConfiguredObject.ID);
+        final List<String> exchangePath = path.subList(0, hierarchy.size() - 3);
+
+        final LegacyConfiguredObject exchange = getNextVersionObject(root, exchangePath, ExchangeController.TYPE);
+
+        final AtomicInteger counter = new AtomicInteger();
+
+        if (ids != null && !ids.isEmpty())
+        {
+            @SuppressWarnings("unchecked")
+            Collection<Binding> bindings = (Collection<Binding>) exchange.getAttribute("bindings");
+            if (bindings != null)
+            {
+                bindings.stream()
+                        .filter(b -> ids.contains(String.valueOf(generateBindingId(exchange,
+                                                                                   b.getDestination(),
+                                                                                   b.getBindingKey()))))
+                        .forEach(b -> {
+
+                            Map<String, Object> params = new LinkedHashMap<>();
+                            params.put("bindingKey", b.getBindingKey());
+                            params.put("destination", b.getDestination());
+                            ManagementResponse r = exchange.invoke("unbind", params, true);
+                            if (Boolean.TRUE.equals(r.getBody()))
+                            {
+                                counter.incrementAndGet();
+                            }
+                        });
+            }
+        }
+        else if (bindingName != null)
+        {
+            Map<String, Object> params = new LinkedHashMap<>();
+            params.put("bindingKey", bindingName);
+            params.put("destination", queueName);
+            ManagementResponse response = exchange.invoke("unbind", params, true);
+            if (Boolean.TRUE.equals(response.getBody()))
+            {
+                counter.incrementAndGet();
+            }
+        }
+        else
+        {
+            throw createBadRequestManagementException("Only deletion by binding full path or ids is supported");
+        }
+
+        return counter.get();
+    }
+
+    private LegacyConfiguredObject getNextVersionObject(final ConfiguredObject<?> root,
+                                                        final List<String> path,
+                                                        final String type)
+    {
+        return (LegacyConfiguredObject) _nextVersionManagementController.get(root,
+                                                                             type.toLowerCase(),
+                                                                             path,
+                                                                             Collections.emptyMap());
+    }
+
+    @Override
+    public ManagementResponse invoke(ConfiguredObject<?> root,
+                                     List<String> path,
+                                     String operation,
+                                     Map<String, Object> parameters,
+                                     boolean isPost, final boolean isSecure) throws ManagementException
+    {
+        Object result = get(root, path, Collections.emptyMap());
+        if (result instanceof Collection && ((Collection)result).size() == 1)
+        {
+            LegacyConfiguredObject  object = (LegacyConfiguredObject) ((Collection<?>)result).iterator().next();
+            return object.invoke(operation, parameters, isSecure);
+        }
+        throw createBadRequestManagementException(String.format("Operation '%s' cannot be invoked for Binding path '%s'",
+                                                                operation,
+                                                                String.join("/", path)));
+    }
+
+
+    @Override
+    public Object getPreferences(ConfiguredObject<?> root,
+                                 List<String> path,
+                                 Map<String, List<String>> parameters) throws ManagementException
+    {
+        throw createBadRequestManagementException("Preferences not supported for Binding");
+    }
+
+    @Override
+    public void setPreferences(ConfiguredObject<?> root,
+                               List<String> path,
+                               Object preferences,
+                               Map<String, List<String>> parameters,
+                               boolean isPost) throws ManagementException
+    {
+        throw createBadRequestManagementException("Preferences not supported for Binding");
+    }
+
+    @Override
+    public int deletePreferences(ConfiguredObject<?> root,
+                                 List<String> path,
+                                 Map<String, List<String>> parameters) throws ManagementException
+    {
+        throw createBadRequestManagementException("Preferences not supported for Binding");
+    }
+
+    @Override
+    public LegacyConfiguredObject convertFromNextVersion(final LegacyConfiguredObject nextVersionObject)
+    {
+        return null;
+    }
+
+    private Collection<LegacyConfiguredObject> getExchangeBindings(final ConfiguredObject<?> root,
+                                                                   final List<String> exchangePath,
+                                                                   final String queueName,
+                                                                   final String bindingName)
+    {
+        final Object result = getNextVersionExchanges(root, exchangePath);
+        if (result instanceof LegacyConfiguredObject)
+        {
+            return getExchangeBindings((LegacyConfiguredObject) result, queueName, bindingName);
+        }
+        else if (result instanceof Collection)
+        {
+            return ((Collection<?>) result).stream()
+                                           .map(LegacyConfiguredObject.class::cast)
+                                           .map(e -> getExchangeBindings(e, queueName, bindingName))
+                                           .flatMap(Collection::stream)
+                                           .collect(Collectors.toList());
+        }
+        else
+        {
+            throw createInternalServerErrorManagementException("Unexpected format of content from next version");
+        }
+
+    }
+
+    private Object getNextVersionExchanges(final ConfiguredObject<?> root, final List<String> exchangePath)
+    {
+        try
+        {
+            return _nextVersionManagementController.get(root,
+                                                        ExchangeController.TYPE.toLowerCase(),
+                                                        exchangePath,
+                                                        Collections.emptyMap());
+        }
+        catch (ManagementException e)
+        {
+            if (e.getStatusCode() != HttpServletResponse.SC_NOT_FOUND)
+            {
+                throw e;
+            }
+            return Collections.emptyList();
+        }
+    }
+
+
+    private Collection<LegacyConfiguredObject> getExchangeBindings(final LegacyConfiguredObject nextVersionExchange,
+                                                                   final String queueName,
+                                                                   final String bindingName)
+    {
+
+        @SuppressWarnings("unchecked")
+        Object items = nextVersionExchange.getAttribute("bindings");
+        if (items instanceof Collection)
+        {
+            return ((Collection<?>) items).stream()
+                                          .map(Binding.class::cast)
+                                          .filter(b -> (queueName == null
+                                                        || "*".equals(queueName)
+                                                        || queueName.equals(b.getDestination()))
+                                                       && (bindingName == null || "*".equals(bindingName) || bindingName
+                                                  .equals(b.getName())))
+                                          .map(b -> createManageableBinding(b, nextVersionExchange))
+                                          .collect(Collectors.toList());
+        }
+        return Collections.emptyList();
+    }
+
+    private LegacyConfiguredObject createManageableBinding(final Binding binding,
+                                                           final LegacyConfiguredObject nextVersionExchange)
+    {
+        final LegacyConfiguredObject nextVersionVirtualHost = nextVersionExchange.getParent(VirtualHostController.TYPE);
+        final LegacyConfiguredObject queue = findNextVersionQueue(binding.getDestination(), nextVersionVirtualHost);
+
+        return new LegacyBinding(_managementController,
+                                 nextVersionExchange,
+                                 queue,
+                                 binding.getBindingKey(),
+                                 binding.getArguments());
+    }
+
+
+    private static LegacyConfiguredObject findNextVersionQueue(final String queueName,
+                                                               final LegacyConfiguredObject nextVersionVirtualHost)
+    {
+        Collection<LegacyConfiguredObject> queues = nextVersionVirtualHost.getChildren(QueueController.TYPE);
+        return queues.stream()
+                     .filter(q -> queueName.equals(q.getAttribute(GenericLegacyConfiguredObject.NAME)))
+                     .findFirst()
+                     .orElse(null);
+    }
+
+
+    private static UUID generateBindingId(final LegacyConfiguredObject exchange,
+                                          final String queueName,
+                                          final String bindingKey)
+    {
+        String pseudoID = exchange.getAttribute(GenericLegacyConfiguredObject.ID) + "/" + queueName + "/" + bindingKey;
+        return UUID.nameUUIDFromBytes(pseudoID.getBytes(StandardCharsets.UTF_8));
+    }
+
+    static class LegacyBinding implements LegacyConfiguredObject
+    {
+        private static final String ARGUMENTS = "arguments";
+        private static final String QUEUE = "queue";
+        private static final String EXCHANGE = "exchange";
+        private static final Collection<String> ATTRIBUTE_NAMES =
+                Collections.unmodifiableSet(Stream.concat(GenericLegacyConfiguredObject.AVAILABLE_ATTRIBUTES.stream(),
+                                                          Stream.of(ARGUMENTS, QUEUE, EXCHANGE))
+                                                  .collect(Collectors.toSet()));
+
+        private final String _bindingKey;
+        private final Map<String, Object> _arguments;
+        private final LegacyConfiguredObject _exchange;
+        private final UUID _id;
+        private final LegacyConfiguredObject _queue;
+        private final LegacyManagementController _controller;
+
+        LegacyBinding(final LegacyManagementController controller,
+                      final LegacyConfiguredObject nextVersionExchange,
+                      final LegacyConfiguredObject nextVersionQueue,
+                      final String bindingKey,
+                      final Map<String, Object> arguments)
+        {
+            _controller = controller;
+            _exchange = _controller.convertFromNextVersion(nextVersionExchange);
+            _queue = _controller.convertFromNextVersion(nextVersionQueue);
+            _bindingKey = bindingKey;
+            _arguments = arguments != null && !arguments.isEmpty() ? arguments : null;
+            String queueName = (String) nextVersionQueue.getAttribute(NAME);
+            _id = generateBindingId(nextVersionExchange, queueName, bindingKey);
+        }
+
+        @Override
+        public Collection<String> getAttributeNames()
+        {
+            return ATTRIBUTE_NAMES;
+        }
+
+        @Override
+        public Object getAttribute(final String name)
+        {
+            if (ID.equalsIgnoreCase(name))
+            {
+                return _id;
+            }
+            else if (NAME.equalsIgnoreCase(name))
+            {
+                return _bindingKey;
+            }
+            else if (STATE.equalsIgnoreCase(name) || DESIRED_STATE.equalsIgnoreCase(name))
+            {
+                return State.ACTIVE;
+            }
+            else if (TYPE.equalsIgnoreCase(name))
+            {
+                return TYPE;
+            }
+            else if (CONTEXT.equalsIgnoreCase(name))
+            {
+                return _exchange.getAttribute(CONTEXT);
+            }
+            else if (QUEUE.equalsIgnoreCase(name))
+            {
+                return _queue;
+            }
+            else if (EXCHANGE.equalsIgnoreCase(name))
+            {
+                return _exchange;
+            }
+            else if (DURABLE.equalsIgnoreCase(name))
+            {
+                return Boolean.TRUE.equals(_queue.getAttribute(DURABLE))
+                       && Boolean.TRUE.equals(_exchange.getAttribute(DURABLE));
+            }
+            else if (LIFETIME_POLICY.equalsIgnoreCase(name))
+            {
+                return _queue.getAttribute(LIFETIME_POLICY);
+            }
+            else if (ARGUMENTS.equalsIgnoreCase(name))
+            {
+                return _arguments;
+            }
+
+            return null;
+        }
+
+        @Override
+        public Object getActualAttribute(final String name)
+        {
+            if (QUEUE.equalsIgnoreCase(name))
+            {
+                return _queue.getAttribute(LegacyConfiguredObject.NAME);
+            }
+            else if (EXCHANGE.equalsIgnoreCase(name))
+            {
+                return _exchange.getAttribute(LegacyConfiguredObject.NAME);
+            }
+            return getAttribute(name);
+        }
+
+        @Override
+        public Collection<LegacyConfiguredObject> getChildren(final String category)
+        {
+            return Collections.emptyList();
+        }
+
+        @Override
+        public String getCategory()
+        {
+            return BindingController.TYPE;
+        }
+
+        @Override
+        public ManagementResponse invoke(final String operation,
+                                         final Map<String, Object> parameters,
+                                         final boolean isSecure)
+        {
+            if ("getStatistics".equals(operation))
+            {
+                return new ControllerManagementResponse(ResponseType.DATA, Collections.emptyMap());
+            }
+            throw createBadRequestManagementException("No operation is available for Binding");
+        }
+
+        @Override
+        public LegacyConfiguredObject getNextVersionConfiguredObject()
+        {
+            return null;
+        }
+
+        public void delete()
+        {
+            Map<String, Object> parameters = new LinkedHashMap<>();
+            parameters.put("bindingKey", getAttribute(NAME));
+            parameters.put("destination", _queue.getAttribute(NAME));
+            _exchange.getNextVersionConfiguredObject().invoke("unbind", parameters, true);
+        }
+
+        @Override
+        public LegacyConfiguredObject getParent(final String category)
+        {
+            if (QueueController.TYPE.equalsIgnoreCase(category))
+            {
+                return _queue;
+            }
+            else if (ExchangeController.TYPE.equalsIgnoreCase(category))
+            {
+                return _exchange;
+            }
+            throw createInternalServerErrorManagementException(String.format("Category %s is not parent of Binding",
+                                                                             category));
+        }
+
+        @Override
+        public boolean isSecureAttribute(final String name)
+        {
+            return false;
+        }
+
+        @Override
+        public boolean isOversizedAttribute(final String name)
+        {
+            return false;
+        }
+
+        @Override
+        public String getContextValue(final String contextKey)
+        {
+            return _exchange.getContextValue(contextKey);
+        }
+
+        @Override
+        public Map<String, Object> getStatistics()
+        {
+            return Collections.emptyMap();
+        }
+    }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/BrokerController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/BrokerController.java
new file mode 100644
index 0000000..28005df
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/BrokerController.java
@@ -0,0 +1,212 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+
+import static org.apache.qpid.server.management.plugin.ManagementException.createGoneManagementException;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.management.plugin.controller.ConverterHelper;
+import org.apache.qpid.server.management.plugin.controller.GenericLegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.management.plugin.controller.TypeController;
+import org.apache.qpid.server.model.ConfiguredObject;
+
+
+public class BrokerController extends LegacyCategoryController
+{
+    public static final String TYPE = "Broker";
+    private static final String CONNECTION_SESSION_COUNT_LIMIT = "connection.sessionCountLimit";
+    private static final String CONNECTION_HEART_BEAT_DELAY = "connection.heartBeatDelay";
+    private static final String CONNECTION_CLOSE_WHEN_NO_ROUTE = "connection.closeWhenNoRoute";
+
+    private static Map<String, String> BROKER_ATTRIBUTES_MOVED_INTO_CONTEXT = new HashMap<>();
+
+    static
+    {
+        BROKER_ATTRIBUTES_MOVED_INTO_CONTEXT.put(CONNECTION_SESSION_COUNT_LIMIT, "qpid.port.sessionCountLimit");
+        BROKER_ATTRIBUTES_MOVED_INTO_CONTEXT.put(CONNECTION_HEART_BEAT_DELAY, "qpid.port.heartbeatDelay");
+        BROKER_ATTRIBUTES_MOVED_INTO_CONTEXT.put(CONNECTION_CLOSE_WHEN_NO_ROUTE, "qpid.port.closeWhenNoRoute");
+    }
+
+    BrokerController(final LegacyManagementController legacyManagementController,
+                     final Set<TypeController> typeControllers)
+    {
+        super(legacyManagementController,
+              TYPE,
+              new String[0],
+              "Broker",
+              typeControllers);
+    }
+
+    @Override
+    public LegacyConfiguredObject convertNextVersionLegacyConfiguredObject(final LegacyConfiguredObject object)
+    {
+        return new LegacyBroker(getManagementController(), object);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    protected Map<String, Object> convertAttributesToNextVersion(final ConfiguredObject<?> root,
+                                                                 final List<String> path,
+                                                                 final Map<String, Object> attributes)
+    {
+        final Map<String, Object> converted = new LinkedHashMap<>(attributes);
+        final Map<String, String> context = (Map<String, String>) converted.get(LegacyConfiguredObject.CONTEXT);
+        final Map<String, String> newContext = new LinkedHashMap<>();
+        if (context != null)
+        {
+            newContext.putAll(context);
+        }
+        converted.put(LegacyConfiguredObject.CONTEXT, newContext);
+        for (String attributeName : BROKER_ATTRIBUTES_MOVED_INTO_CONTEXT.keySet())
+        {
+            Object value = converted.remove(attributeName);
+            if (value != null)
+            {
+                newContext.put(BROKER_ATTRIBUTES_MOVED_INTO_CONTEXT.get(attributeName), String.valueOf(value));
+            }
+        }
+
+        converted.remove("statisticsReportingResetEnabled");
+
+        final Object statisticsReportingPeriod = converted.get("statisticsReportingPeriod");
+        if (statisticsReportingPeriod != null
+            && !newContext.containsKey("qpid.broker.statisticsReportPattern")
+            && (ConverterHelper.toInt(statisticsReportingPeriod) > 0 || ConverterHelper.isContextVariable(
+                statisticsReportingPeriod)))
+        {
+            newContext.put("qpid.broker.statisticsReportPattern",
+                           "messagesIn=${messagesIn}, bytesIn=${bytesIn:byteunit}, messagesOut=${messagesOut}, bytesOut=${bytesOut:byteunit}");
+        }
+
+        return converted;
+    }
+
+    static class LegacyBroker extends GenericLegacyConfiguredObject
+    {
+        private static final String MODEL_VERSION = "modelVersion";
+
+        LegacyBroker(final LegacyManagementController managementController,
+                     final LegacyConfiguredObject nextVersionLegacyConfiguredObject)
+        {
+            super(managementController, nextVersionLegacyConfiguredObject, BrokerController.TYPE);
+        }
+
+        @Override
+        public Collection<String> getAttributeNames()
+        {
+            return Stream.concat(super.getAttributeNames().stream(),
+                                 BROKER_ATTRIBUTES_MOVED_INTO_CONTEXT.keySet().stream()).collect(
+                    Collectors.toSet());
+        }
+
+        @Override
+        public Object getAttribute(final String name)
+        {
+            if (MODEL_VERSION.equals(name))
+            {
+                return getManagementController().getVersion();
+            }
+            else if (BROKER_ATTRIBUTES_MOVED_INTO_CONTEXT.containsKey(name))
+            {
+                Object value = getMovedAttribute(name);
+                if (value != null)
+                {
+                    if (CONNECTION_SESSION_COUNT_LIMIT.equals(name))
+                    {
+                        return ConverterHelper.toInt(value);
+                    }
+                    else if (CONNECTION_HEART_BEAT_DELAY.equals(name))
+                    {
+                        return ConverterHelper.toLong(value);
+                    }
+                    else if (CONNECTION_CLOSE_WHEN_NO_ROUTE.equals(name))
+                    {
+                        return ConverterHelper.toBoolean(value);
+                    }
+                }
+                return null;
+            }
+            return super.getAttribute(name);
+        }
+
+        @Override
+        public Object getActualAttribute(final String name)
+        {
+            if (MODEL_VERSION.equals(name))
+            {
+                return getManagementController().getVersion();
+            }
+            else if (BROKER_ATTRIBUTES_MOVED_INTO_CONTEXT.containsKey(name))
+            {
+                return getMovedAttribute(name);
+            }
+            return super.getActualAttribute(name);
+        }
+
+        @SuppressWarnings("unchecked")
+        private Object getMovedAttribute(final String name)
+        {
+            Map<String, String> context = (Map<String, String>) super.getAttribute(LegacyConfiguredObject.CONTEXT);
+            if (context != null)
+            {
+                String contextVariable = BROKER_ATTRIBUTES_MOVED_INTO_CONTEXT.get(name);
+                return context.get(contextVariable);
+            }
+            return null;
+        }
+
+        @Override
+        public ManagementResponse invoke(final String operation,
+                                         final Map<String, Object> parameters,
+                                         final boolean isSecure)
+        {
+            if ("resetStatistics".equalsIgnoreCase(operation))
+            {
+                throw createGoneManagementException("Method 'resetStatistics' was removed");
+            }
+            return super.invoke(operation, parameters, isSecure);
+        }
+
+        @Override
+        public boolean isSecureAttribute(final String name)
+        {
+            return !BROKER_ATTRIBUTES_MOVED_INTO_CONTEXT.containsKey(name) && super.isSecureAttribute(name);
+        }
+
+        @Override
+        public boolean isOversizedAttribute(final String name)
+        {
+            return !BROKER_ATTRIBUTES_MOVED_INTO_CONTEXT.containsKey(name) && super.isOversizedAttribute(name);
+        }
+    }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/ConsumerController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/ConsumerController.java
new file mode 100644
index 0000000..9f215e7
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/ConsumerController.java
@@ -0,0 +1,257 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import static org.apache.qpid.server.management.plugin.ManagementException.createBadRequestManagementException;
+import static org.apache.qpid.server.management.plugin.ManagementException.createInternalServerErrorManagementException;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.ManagementException;
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.management.plugin.controller.CategoryController;
+import org.apache.qpid.server.management.plugin.controller.GenericLegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.model.ConfiguredObject;
+
+public class ConsumerController implements CategoryController
+{
+    public static final String TYPE = "Consumer";
+    private final LegacyManagementController _managementController;
+
+    ConsumerController(final LegacyManagementController managementController)
+    {
+        _managementController = managementController;
+    }
+
+    @Override
+    public String getCategory()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public String getNextVersionCategory()
+    {
+        return TYPE;
+    }
+
+    @Override
+    public String getDefaultType()
+    {
+        return null;
+    }
+
+    @Override
+    public String[] getParentCategories()
+    {
+        return new String[]{SessionController.TYPE, QueueController.TYPE};
+    }
+
+    @Override
+    public LegacyManagementController getManagementController()
+    {
+        return _managementController;
+    }
+
+    private ManagementController getNextVersionManagementController()
+    {
+        return _managementController.getNextVersionManagementController();
+    }
+
+    @Override
+    public Object get(final ConfiguredObject<?> root,
+                      final List<String> path,
+                      final Map<String, List<String>> parameters) throws ManagementException
+    {
+        final Collection<String> hierarchy = _managementController.getCategoryHierarchy(root, TYPE);
+        final String consumerName = path.size() == hierarchy.size() ? path.get(hierarchy.size() - 1) : null;
+        final String queueName = path.size() >= hierarchy.size() - 1 ? path.get(hierarchy.size() - 2) : null;
+        final String sessionName = path.size() >= hierarchy.size() - 2 ? path.get(hierarchy.size() - 3) : null;
+
+        List<String> virtualHostPath = path;
+        if (virtualHostPath.size() > hierarchy.size() - 3)
+        {
+            virtualHostPath = virtualHostPath.subList(0, hierarchy.size() - 3);
+        }
+
+        final Object queues = getNextVersionManagementController().get(root,
+                                                                       "Queue",
+                                                                       virtualHostPath,
+                                                                       Collections.emptyMap());
+
+        Collection<LegacyConfiguredObject> consumers;
+        if (queues instanceof LegacyConfiguredObject)
+        {
+            consumers = getQueueConsumers(sessionName, queueName, consumerName, (LegacyConfiguredObject) queues);
+        }
+        else if (queues instanceof Collection)
+        {
+            consumers = ((Collection<?>) queues).stream()
+                                           .map(LegacyConfiguredObject.class::cast)
+                                           .map(q -> getQueueConsumers(sessionName, queueName, consumerName, q))
+                                           .flatMap(Collection::stream)
+                                           .collect(Collectors.toList());
+        }
+        else
+        {
+            throw createInternalServerErrorManagementException("Unexpected consumer format from next version");
+        }
+        return consumers;
+    }
+
+
+    @Override
+    public int delete(ConfiguredObject<?> root,
+                      List<String> path,
+                      Map<String, List<String>> parameters) throws ManagementException
+    {
+        throw createBadRequestManagementException("Consumer cannot be deleted via management interfaces");
+    }
+
+    @Override
+    public LegacyConfiguredObject createOrUpdate(ConfiguredObject<?> root,
+                                                 List<String> path,
+                                                 Map<String, Object> attributes,
+                                                 boolean isPost) throws ManagementException
+    {
+        throw createBadRequestManagementException("Consumer cannot be created or updated via management interfaces");
+    }
+
+    @Override
+    public ManagementResponse invoke(ConfiguredObject<?> root,
+                                     List<String> path,
+                                     String operation,
+                                     Map<String, Object> parameters,
+                                     boolean isPost, final boolean isSecure) throws ManagementException
+    {
+        Object result = get( root, path, Collections.emptyMap());
+        if (result instanceof Collection && ((Collection)result).size() == 1)
+        {
+            LegacyConfiguredObject  object = (LegacyConfiguredObject) ((Collection<?>)result).iterator().next();
+            return object.invoke(operation, parameters, isSecure);
+        }
+
+        throw createBadRequestManagementException(String.format("Cannot find consumer for path %s",
+                                                                String.join("/" + path)));
+    }
+
+    @Override
+    public Object getPreferences(ConfiguredObject<?> root,
+                                 List<String> path,
+                                 Map<String, List<String>> parameters) throws ManagementException
+    {
+        throw createBadRequestManagementException("Preferences not supported for Consumer");
+    }
+
+    @Override
+    public void setPreferences(ConfiguredObject<?> root,
+                               List<String> path,
+                               Object preferences,
+                               Map<String, List<String>> parameters,
+                               boolean isPost) throws ManagementException
+    {
+        throw createBadRequestManagementException("Preferences not supported for Consumer");
+    }
+
+    @Override
+    public int deletePreferences(ConfiguredObject<?> root,
+                                 List<String> path,
+                                 Map<String, List<String>> parameters) throws ManagementException
+    {
+        throw createBadRequestManagementException("Preferences not supported for Consumer");
+    }
+
+    @Override
+    public LegacyConfiguredObject convertFromNextVersion(final LegacyConfiguredObject nextVersionObject)
+    {
+        return new LegacyConsumer(getManagementController(), nextVersionObject);
+    }
+
+
+    private Collection<LegacyConfiguredObject> getQueueConsumers(final String sessionName,
+                                                                 final String queueName,
+                                                                 final String consumerName,
+                                                                 final LegacyConfiguredObject nextVersionQueue)
+    {
+        if (queueName == null
+            || queueName.equals("*")
+            || queueName.equals(nextVersionQueue.getAttribute(LegacyConfiguredObject.NAME)))
+        {
+            Collection<LegacyConfiguredObject> queueConsumers = nextVersionQueue.getChildren(ConsumerController.TYPE);
+            if (queueConsumers != null)
+            {
+                return queueConsumers.stream()
+                                     .filter(c -> consumerName == null
+                                                  || "*".equals(consumerName)
+                                                  || consumerName.equals(c.getAttribute("name")))
+                                     .filter(c -> {
+                                         if (sessionName == null || "*".equals(sessionName))
+                                         {
+                                             return true;
+                                         }
+                                         else
+                                         {
+                                             Object obj = c.getAttribute("session");
+                                             if (obj instanceof LegacyConfiguredObject)
+                                             {
+                                                 return sessionName.equals(((LegacyConfiguredObject) obj).getAttribute(
+                                                         LegacyConfiguredObject.NAME));
+                                             }
+                                             return false;
+                                         }
+                                     })
+                                     .map(this::convertFromNextVersion)
+                                     .collect(Collectors.toList());
+            }
+        }
+        return Collections.emptyList();
+    }
+
+    static class LegacyConsumer extends GenericLegacyConfiguredObject
+    {
+        LegacyConsumer(final LegacyManagementController managementController,
+                       final LegacyConfiguredObject nextVersionLegacyConfiguredObject)
+        {
+            super(managementController, nextVersionLegacyConfiguredObject, ConsumerController.TYPE);
+        }
+
+        @Override
+        public LegacyConfiguredObject getParent(final String category)
+        {
+            if (SessionController.TYPE.equals(category))
+            {
+                final LegacyConfiguredObject nextVersionConsumer = getNextVersionLegacyConfiguredObject();
+                final LegacyConfiguredObject nextVersionSession =
+                        (LegacyConfiguredObject) nextVersionConsumer.getAttribute(SessionController.TYPE.toLowerCase());
+                return getManagementController().convertFromNextVersion(nextVersionSession);
+            }
+
+            return getManagementController().convertFromNextVersion(getNextVersionLegacyConfiguredObject().getParent(category));
+        }
+    }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/DestinationController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/DestinationController.java
new file mode 100644
index 0000000..df70c1b
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/DestinationController.java
@@ -0,0 +1,207 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import static org.apache.qpid.server.management.plugin.ManagementException.createBadRequestManagementException;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.qpid.server.management.plugin.controller.GenericLegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.management.plugin.controller.TypeController;
+import org.apache.qpid.server.model.AlternateBinding;
+import org.apache.qpid.server.model.ConfiguredObject;
+
+public class DestinationController extends LegacyCategoryController
+{
+
+    private static final String ALTERNATE_BINDING = "alternateBinding";
+
+    DestinationController(final LegacyManagementController legacyManagementController,
+                          final String name,
+                          final String[] parentCategories,
+                          final String defaultType,
+                          final Set<TypeController> typeControllers)
+    {
+        super(legacyManagementController,
+              name,
+              parentCategories,
+              defaultType,
+              typeControllers);
+    }
+
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Map<String, Object> convertAttributesToNextVersion(final ConfiguredObject<?> root,
+                                                              final List<String> path,
+                                                              final Map<String, Object> attributes)
+    {
+        if (attributes.containsKey(LegacyDestination.ALTERNATE_EXCHANGE))
+        {
+            final Map<String, Object> converted = new LinkedHashMap<>(attributes);
+            final String alternateExchange = (String) converted.remove(LegacyDestination.ALTERNATE_EXCHANGE);
+            final LegacyConfiguredObject exchange = findExchange(root,
+                                                                 path,
+                                                                 object -> alternateExchange.equals(object.getAttribute(LegacyConfiguredObject.ID))
+                                                                           || alternateExchange.equals(object.getAttribute(LegacyConfiguredObject.NAME)));
+            if (exchange != null)
+            {
+                converted.put(ALTERNATE_BINDING,
+                              Collections.singletonMap("destination",
+                                                       exchange.getAttribute(LegacyConfiguredObject.NAME)));
+            }
+            else
+            {
+                throw createBadRequestManagementException(String.format("Cannot find alternate exchange '%s'",
+                                                                        alternateExchange));
+            }
+            return converted;
+        }
+        return attributes;
+    }
+
+    private LegacyConfiguredObject findExchange(final ConfiguredObject<?> root,
+                                                final List<String> path,
+                                                final Predicate<LegacyConfiguredObject> predicate)
+    {
+        final Collection<String> hierarchy =
+                getNextVersionManagementController().getCategoryHierarchy(root, ExchangeController.TYPE);
+
+        final List<String> exchangePath = path.size() > hierarchy.size() - 1 ? path.subList(0, hierarchy.size() - 1) : path;
+        final Object result = getNextVersionManagementController().get(root,
+                                                                       ExchangeController.TYPE,
+                                                                       exchangePath,
+                                                                       Collections.emptyMap());
+        if (result instanceof Collection)
+        {
+            final Collection<?> exchanges = (Collection<?>) result;
+            return exchanges.stream()
+                            .filter(LegacyConfiguredObject.class::isInstance)
+                            .map(LegacyConfiguredObject.class::cast)
+                            .filter(predicate)
+                            .findFirst()
+                            .orElse(null);
+        }
+        else
+        {
+            throw createBadRequestManagementException("Cannot find alternate exchange");
+        }
+    }
+
+    public static class LegacyDestination extends GenericLegacyConfiguredObject
+    {
+        static final String ALTERNATE_EXCHANGE = "alternateExchange";
+
+        LegacyDestination(final LegacyManagementController managementController,
+                          final LegacyConfiguredObject nextVersionDestination,
+                          final String category)
+        {
+            super(managementController, nextVersionDestination, category);
+        }
+
+        @Override
+        public Collection<String> getAttributeNames()
+        {
+            return Stream.concat(super.getAttributeNames().stream(),
+                                 Stream.of(ALTERNATE_EXCHANGE)).collect(Collectors.toSet());
+        }
+
+        @Override
+        public Object getAttribute(final String name)
+        {
+            return getAttributeInternal(name, false);
+        }
+
+
+        @Override
+        public Object getActualAttribute(final String name)
+        {
+            return getAttributeInternal(name, true);
+        }
+
+        protected Object getAttributeInternal(final String name, boolean isActual)
+        {
+            if (ALTERNATE_EXCHANGE.equals(name))
+            {
+                final Object altBinding = getAttribute(ALTERNATE_BINDING, isActual);
+                if (altBinding instanceof AlternateBinding)
+                {
+                    final AlternateBinding alternateBinding = (AlternateBinding) altBinding;
+
+                    final Collection<LegacyConfiguredObject> exchanges =
+                            getNextVersionLegacyConfiguredObject().getParent(VirtualHostController.TYPE)
+                                                                  .getChildren(ExchangeController.TYPE);
+
+                    final LegacyConfiguredObject altExchange = exchanges.stream()
+                                                                  .filter(e -> alternateBinding.getDestination()
+                                                                                               .equals(e.getAttribute(NAME)))
+                                                                  .findFirst()
+                                                                  .orElse(null);
+                    if (altExchange != null)
+                    {
+                        return getManagementController().convertFromNextVersion(altExchange);
+                    }
+                }
+                return null;
+            }
+            return getAttribute(name, isActual);
+        }
+
+        Object getAttribute(String name, boolean isActual)
+        {
+            if (isActual)
+            {
+                return super.getActualAttribute(name);
+            }
+            return super.getAttribute(name);
+        }
+
+        @Override
+        public boolean isSecureAttribute(final String name)
+        {
+            if (ALTERNATE_EXCHANGE.equals(name))
+            {
+                return super.isSecureAttribute(ALTERNATE_BINDING);
+            }
+            return super.isSecureAttribute(name);
+        }
+
+        @Override
+        public boolean isOversizedAttribute(final String name)
+        {
+            if (ALTERNATE_EXCHANGE.equals(name))
+            {
+                return super.isOversizedAttribute(ALTERNATE_BINDING);
+            }
+            return super.isOversizedAttribute(name);
+        }
+    }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/ExchangeController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/ExchangeController.java
new file mode 100644
index 0000000..c5a63a1
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/ExchangeController.java
@@ -0,0 +1,92 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.management.plugin.controller.TypeController;
+import org.apache.qpid.server.model.Binding;
+
+public class ExchangeController extends DestinationController
+{
+
+    public static final String TYPE = "Exchange";
+
+    ExchangeController(final LegacyManagementController legacyManagementController,
+                       final Set<TypeController> typeControllers)
+    {
+        super(legacyManagementController,
+              TYPE,
+              new String[]{VirtualHostController.TYPE},
+              null,
+              typeControllers);
+    }
+
+    @Override
+    protected LegacyConfiguredObject convertNextVersionLegacyConfiguredObject(final LegacyConfiguredObject object)
+    {
+        return new LegacyExchange(getManagementController(), object);
+    }
+
+    public static class LegacyExchange extends LegacyDestination
+    {
+        LegacyExchange(final LegacyManagementController managementController,
+                       final LegacyConfiguredObject nextVersionQueue)
+        {
+            super(managementController, nextVersionQueue, ExchangeController.TYPE);
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Collection<LegacyConfiguredObject> getChildren(final String category)
+        {
+            if (BindingController.TYPE.equals(category))
+            {
+                Collection<Binding> bindings = (Collection<Binding>) getAttribute("bindings");
+                if (bindings != null)
+                {
+                    Map<String, LegacyConfiguredObject> queues =
+                            getNextVersionLegacyConfiguredObject().getParent(VirtualHostController.TYPE)
+                                                                  .getChildren(QueueController.TYPE)
+                                                                  .stream()
+                                                                  .collect(Collectors.toMap(q -> (String) q.getAttribute(
+                                                                          LegacyConfiguredObject.NAME),
+                                                                                            q -> q));
+                    return bindings.stream()
+                                   .map(b -> new BindingController.LegacyBinding(getManagementController(),
+                                                                             getNextVersionLegacyConfiguredObject(),
+                                                                             queues.get(b.getName()),
+                                                                             b.getBindingKey(),
+                                                                             b.getArguments()))
+                                   .collect(Collectors.toList());
+                }
+                return Collections.emptyList();
+            }
+            return super.getChildren(category);
+        }
+    }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/LegacyCategoryController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/LegacyCategoryController.java
new file mode 100644
index 0000000..fb347f7
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/LegacyCategoryController.java
@@ -0,0 +1,62 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import java.util.Set;
+
+import org.apache.qpid.server.management.plugin.controller.GenericCategoryController;
+import org.apache.qpid.server.management.plugin.controller.GenericLegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.management.plugin.controller.TypeController;
+
+public class LegacyCategoryController extends GenericCategoryController
+{
+
+    private final String[] _parentCategories;
+
+
+    LegacyCategoryController(final LegacyManagementController managementController,
+                             final String name,
+                             final String[] parentCategories,
+                             final String defaultType,
+                             final Set<TypeController> typeControllers)
+    {
+        super(managementController,
+              managementController.getNextVersionManagementController(),
+              name,
+              defaultType,
+              typeControllers);
+        _parentCategories = parentCategories;
+    }
+
+    @Override
+    public String[] getParentCategories()
+    {
+        return _parentCategories;
+    }
+
+    @Override
+    protected LegacyConfiguredObject convertNextVersionLegacyConfiguredObject(final LegacyConfiguredObject object)
+    {
+        return new GenericLegacyConfiguredObject(getManagementController(), object, getCategory());
+    }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/LegacyCategoryControllerFactory.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/LegacyCategoryControllerFactory.java
new file mode 100644
index 0000000..9f49dab
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/LegacyCategoryControllerFactory.java
@@ -0,0 +1,268 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.qpid.server.management.plugin.controller.CategoryControllerFactory;
+import org.apache.qpid.server.management.plugin.controller.CategoryController;
+
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.management.plugin.controller.v6_1.LegacyManagementControllerFactory;
+import org.apache.qpid.server.plugin.PluggableService;
+
+@PluggableService
+public class LegacyCategoryControllerFactory implements CategoryControllerFactory
+{
+    static final String CATEGORY_BROKER = BrokerController.TYPE;
+    private static final String CATEGORY_BROKER_LOGGER = "BrokerLogger";
+    private static final String CATEGORY_BROKER_LOG_INCLUSION_RULE = "BrokerLogInclusionRule";
+    private static final String CATEGORY_AUTHENTICATION_PROVIDER = "AuthenticationProvider";
+    private static final String CATEGORY_USER = "User";
+    private static final String CATEGORY_ACCESS_CONTROL_PROVIDER = "AccessControlProvider";
+    private static final String CATEGORY_PLUGIN = "Plugin";
+    private static final String CATEGORY_TRUST_STORE = "TrustStore";
+    private static final String CATEGORY_KEY_STORE = "KeyStore";
+    static final String CATEGORY_PORT = PortController.TYPE;
+    private static final String CATEGORY_VIRTUAL_HOST_ALIAS = "VirtualHostAlias";
+    private static final String CATEGORY_GROUP_PROVIDER = "GroupProvider";
+    private static final String CATEGORY_GROUP = "Group";
+    private static final String CATEGORY_GROUP_MEMBER = "GroupMember";
+    static final String CATEGORY_VIRTUAL_HOST_NODE = "VirtualHostNode";
+    private static final String CATEGORY_REMOTE_REPLICATION_NODE = "RemoteReplicationNode";
+    static final String CATEGORY_VIRTUAL_HOST = VirtualHostController.TYPE;
+    private static final String CATEGORY_VIRTUAL_HOST_LOGGER = "VirtualHostLogger";
+    private static final String CATEGORY_VIRTUAL_HOST_LOG_INCLUSION_RULE = "VirtualHostLogInclusionRule";
+    private static final String CATEGORY_VIRTUAL_HOST_ACCESS_CONTROL_PROVIDER = "VirtualHostAccessControlProvider";
+    static final String CATEGORY_EXCHANGE = ExchangeController.TYPE;
+    static final String CATEGORY_QUEUE = QueueController.TYPE;
+    private static final String CATEGORY_BINDING = BindingController.TYPE;
+    static final String CATEGORY_CONSUMER = ConsumerController.TYPE;
+    static final String CATEGORY_CONNECTION = "Connection";
+    static final String CATEGORY_SESSION = SessionController.TYPE;
+    static final Set<String> SUPPORTED_CATEGORIES =
+            Collections.unmodifiableSet(new HashSet<>(Arrays.asList(CATEGORY_BROKER,
+                                                                    CATEGORY_BROKER_LOGGER,
+                                                                    CATEGORY_BROKER_LOG_INCLUSION_RULE,
+                                                                    CATEGORY_AUTHENTICATION_PROVIDER,
+                                                                    CATEGORY_USER,
+                                                                    CATEGORY_ACCESS_CONTROL_PROVIDER,
+                                                                    CATEGORY_PLUGIN,
+                                                                    CATEGORY_TRUST_STORE,
+                                                                    CATEGORY_KEY_STORE,
+                                                                    CATEGORY_PORT,
+                                                                    CATEGORY_VIRTUAL_HOST_ALIAS,
+                                                                    CATEGORY_GROUP_PROVIDER,
+                                                                    CATEGORY_GROUP,
+                                                                    CATEGORY_GROUP_MEMBER,
+                                                                    CATEGORY_VIRTUAL_HOST_NODE,
+                                                                    CATEGORY_REMOTE_REPLICATION_NODE,
+                                                                    CATEGORY_VIRTUAL_HOST,
+                                                                    CATEGORY_VIRTUAL_HOST_LOGGER,
+                                                                    CATEGORY_VIRTUAL_HOST_LOG_INCLUSION_RULE,
+                                                                    CATEGORY_VIRTUAL_HOST_ACCESS_CONTROL_PROVIDER,
+                                                                    CATEGORY_EXCHANGE,
+                                                                    CATEGORY_QUEUE,
+                                                                    CATEGORY_BINDING,
+                                                                    CATEGORY_CONSUMER,
+                                                                    CATEGORY_CONNECTION,
+                                                                    CATEGORY_SESSION
+                                                                   )));
+
+    private static final Map<String, String> DEFAULT_TYPES = Collections.unmodifiableMap(new HashMap<String, String>()
+    {
+        {
+            put(CATEGORY_BROKER_LOGGER, "Broker");
+            put(CATEGORY_TRUST_STORE, "FileTrustStore");
+            put(CATEGORY_KEY_STORE, "FileKeyStore");
+            put(CATEGORY_GROUP, "ManagedGroup");
+            put(CATEGORY_GROUP_MEMBER, "ManagedGroupMember");
+            put(CATEGORY_VIRTUAL_HOST, "ProvidedStore");
+            put(CATEGORY_QUEUE, "standard");
+        }
+    });
+
+    @Override
+    public CategoryController createController(final String type,
+                                               final LegacyManagementController legacyManagementController)
+    {
+        switch (type)
+        {
+            case CATEGORY_ACCESS_CONTROL_PROVIDER:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_BROKER},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_BROKER:
+                return new BrokerController(legacyManagementController,
+                                            legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_BROKER_LOGGER:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_BROKER},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_BROKER_LOG_INCLUSION_RULE:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_BROKER_LOGGER},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_AUTHENTICATION_PROVIDER:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_BROKER},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_USER:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_AUTHENTICATION_PROVIDER},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_PORT:
+                return new PortController(legacyManagementController,
+                                          legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_VIRTUAL_HOST_ALIAS:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_VIRTUAL_HOST_ALIAS},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_PLUGIN:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_BROKER},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_TRUST_STORE:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_BROKER},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_KEY_STORE:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_BROKER},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_GROUP_PROVIDER:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_BROKER},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_GROUP:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_GROUP_PROVIDER},
+                                                    null,
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_GROUP_MEMBER:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_GROUP},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_VIRTUAL_HOST_NODE:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_BROKER},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_REMOTE_REPLICATION_NODE:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_VIRTUAL_HOST_NODE},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_VIRTUAL_HOST:
+                return new VirtualHostController(legacyManagementController,
+                                                 legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_VIRTUAL_HOST_LOGGER:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_VIRTUAL_HOST},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_VIRTUAL_HOST_LOG_INCLUSION_RULE:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_VIRTUAL_HOST_LOGGER},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_VIRTUAL_HOST_ACCESS_CONTROL_PROVIDER:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_VIRTUAL_HOST},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_EXCHANGE:
+                return new ExchangeController(legacyManagementController,
+                                              legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_QUEUE:
+                return new QueueController(legacyManagementController,
+                                           legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_BINDING:
+                return new BindingController(legacyManagementController
+                );
+            case CATEGORY_CONNECTION:
+                return new LegacyCategoryController(legacyManagementController,
+                                                    type,
+                                                    new String[]{CATEGORY_PORT, CATEGORY_VIRTUAL_HOST},
+                                                    DEFAULT_TYPES.get(type),
+                                                    legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_SESSION:
+                return new SessionController(legacyManagementController,
+                                             legacyManagementController.getTypeControllersByCategory(type));
+            case CATEGORY_CONSUMER:
+                return new ConsumerController(legacyManagementController
+                );
+            default:
+                throw new IllegalArgumentException(String.format("Unsupported category '%s'", type));
+        }
+    }
+
+    @Override
+    public Set<String> getSupportedCategories()
+    {
+        return SUPPORTED_CATEGORIES;
+    }
+
+    @Override
+    public String getModelVersion()
+    {
+        return LegacyManagementControllerFactory.MODEL_VERSION;
+    }
+
+    @Override
+    public String getType()
+    {
+        return LegacyCategoryControllerFactory.class.getName();
+    }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/PortController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/PortController.java
new file mode 100644
index 0000000..1564b74
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/PortController.java
@@ -0,0 +1,140 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.qpid.server.management.plugin.ManagementException;
+import org.apache.qpid.server.management.plugin.controller.GenericLegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.management.plugin.controller.TypeController;
+import org.apache.qpid.server.model.ConfiguredObject;
+
+public class PortController extends LegacyCategoryController
+{
+    public static final String TYPE = "Port";
+
+    PortController(final LegacyManagementController legacyManagementController,
+                   final Set<TypeController> typeControllers)
+    {
+        super(legacyManagementController,
+              TYPE,
+              new String[]{BrokerController.TYPE},
+              null,
+              typeControllers);
+    }
+
+    @Override
+    protected LegacyConfiguredObject convertNextVersionLegacyConfiguredObject(final LegacyConfiguredObject object)
+    {
+        return new LegacyPort(getManagementController(), object);
+    }
+
+    @Override
+    public Map<String, Object> convertAttributesToNextVersion(final ConfiguredObject<?> root,
+                                                              final List<String> path,
+                                                              final Map<String, Object> attributes)
+    {
+        Map<String, Object> portAttributes = attributes;
+        if ("HTTP".equals(portAttributes.get("type")) && portAttributes.containsKey("context"))
+        {
+            @SuppressWarnings("unchecked")
+            Map<String, String> context = (Map<String, String>) portAttributes.get("context");
+            if (context.containsKey("port.http.additionalInternalThreads")
+                || context.containsKey("port.http.maximumQueuedRequests"))
+            {
+                Map<String, Object> updatedAttributes = new LinkedHashMap<>(portAttributes);
+                updatedAttributes.put("context", convertContextToNextVersion(context));
+                portAttributes = updatedAttributes;
+            }
+        }
+        return portAttributes;
+    }
+
+    private Map<String, String> convertContextToNextVersion(final Map<String, String> context)
+            throws ManagementException
+    {
+        if (context.containsKey("port.http.additionalInternalThreads")
+            || context.containsKey("port.http.maximumQueuedRequests"))
+        {
+            Map<String, String> updatedContext = new LinkedHashMap<>(context);
+            updatedContext.remove("port.http.additionalInternalThreads");
+            String acceptorsBacklog = updatedContext.remove("port.http.maximumQueuedRequests");
+            if (acceptorsBacklog != null)
+            {
+                updatedContext.put("qpid.port.http.acceptBacklog", acceptorsBacklog);
+            }
+            return updatedContext;
+        }
+        return context;
+    }
+
+    static class LegacyPort extends GenericLegacyConfiguredObject
+    {
+        LegacyPort(final LegacyManagementController managementController,
+                   final LegacyConfiguredObject nextVersionQueue)
+        {
+            super(managementController, nextVersionQueue, PortController.TYPE);
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Object getAttribute(final String name)
+        {
+            if (CONTEXT.equals(name))
+            {
+                if ("HTTP".equals(super.getAttribute(TYPE)))
+                {
+                    Map<String, String> context = (Map<String, String>) super.getAttribute(CONTEXT);
+                    return convertContextIfRequired(context);
+                }
+            }
+            return super.getAttribute(name);
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Object getActualAttribute(final String name)
+        {
+            if (CONTEXT.equals(name) && "HTTP".equals(super.getAttribute(TYPE)))
+            {
+                Map<String, String> context = (Map<String, String>) super.getActualAttribute(CONTEXT);
+                return convertContextIfRequired(context);
+            }
+            return super.getActualAttribute(name);
+        }
+
+        private Object convertContextIfRequired(final Map<String, String> context)
+        {
+            if (context != null && context.containsKey("qpid.port.http.acceptBacklog"))
+            {
+                Map<String, String> updatedContext = new LinkedHashMap<>(context);
+                updatedContext.put("port.http.maximumQueuedRequests", updatedContext.remove("qpid.port.http.acceptBacklog"));
+                return updatedContext;
+            }
+            return context;
+        }
+    }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/QueueController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/QueueController.java
new file mode 100644
index 0000000..10d6400
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/QueueController.java
@@ -0,0 +1,273 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import org.apache.qpid.server.management.plugin.controller.ConverterHelper;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.management.plugin.controller.TypeController;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.ConfiguredObject;
+
+public class QueueController extends DestinationController
+{
+    public static final String TYPE = "Queue";
+
+    QueueController(final LegacyManagementController legacyManagementController,
+                    final Set<TypeController> typeControllers)
+    {
+        super(legacyManagementController,
+              TYPE,
+              new String[]{VirtualHostController.TYPE},
+              "standard",
+              typeControllers);
+    }
+
+    @Override
+    protected LegacyConfiguredObject convertNextVersionLegacyConfiguredObject(final LegacyConfiguredObject object)
+    {
+        return new LegacyQueue(getManagementController(), object);
+    }
+
+    @Override
+    public Map<String, Object> convertAttributesToNextVersion(final ConfiguredObject<?> root,
+                                                              final List<String> path,
+                                                              final Map<String, Object> attributes)
+    {
+        Map<String, Object> converted = new LinkedHashMap<>(attributes);
+        Object queueFlowControlSizeBytes = converted.remove("queueFlowControlSizeBytes");
+        Object queueFlowResumeSizeBytes = converted.remove("queueFlowResumeSizeBytes");
+        if (queueFlowControlSizeBytes != null)
+        {
+            long queueFlowControlSizeBytesValue = ConverterHelper.toLong(queueFlowControlSizeBytes);
+            if (queueFlowControlSizeBytesValue > 0)
+            {
+                if (queueFlowResumeSizeBytes != null)
+                {
+                    long queueFlowResumeSizeBytesValue = ConverterHelper.toLong(queueFlowResumeSizeBytes);
+                    double ratio = ((double) queueFlowResumeSizeBytesValue)
+                                   / ((double) queueFlowControlSizeBytesValue);
+                    String flowResumeLimit = String.format("%.2f", ratio * 100.0);
+
+                    Object context = converted.get("context");
+                    Map<String, String> contextMap;
+                    if (context instanceof Map)
+                    {
+                        contextMap = (Map) context;
+                    }
+                    else
+                    {
+                        contextMap = new LinkedHashMap<>();
+                        converted.put("context", contextMap);
+                    }
+                    contextMap.put("queue.queueFlowResumeLimit", flowResumeLimit);
+                }
+                converted.put("overflowPolicy", "PRODUCER_FLOW_CONTROL");
+                converted.put("maximumQueueDepthBytes", queueFlowControlSizeBytes);
+            }
+        }
+
+        if (converted.containsKey("messageGroupKey"))
+        {
+            if (converted.containsKey("messageGroupSharedGroups")
+                && ConverterHelper.toBoolean(converted.remove("messageGroupSharedGroups")))
+            {
+                converted.put("messageGroupType", "SHARED_GROUPS");
+            }
+            else
+            {
+                converted.put("messageGroupType", "STANDARD");
+            }
+            Object oldMessageGroupKey = converted.remove("messageGroupKey");
+            if (!"JMSXGroupId".equals(oldMessageGroupKey))
+            {
+                converted.put("messageGroupKeyOverride", oldMessageGroupKey);
+            }
+        }
+        else
+        {
+            converted.put("messageGroupType", "NONE");
+        }
+
+        return super.convertAttributesToNextVersion(root, path, converted);
+    }
+
+
+    static class LegacyQueue extends LegacyDestination
+    {
+        static final String QUEUE_FLOW_RESUME_SIZE_BYTES = "queueFlowResumeSizeBytes";
+        static final String QUEUE_FLOW_CONTROL_SIZE_BYTES = "queueFlowControlSizeBytes";
+        static final String MESSAGE_GROUP_SHARED_GROUPS = "messageGroupSharedGroups";
+        static final String MESSAGE_GROUP_KEY = "messageGroupKey";
+
+        Set<String> MOVED_ATTRIBUTES = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(
+                QUEUE_FLOW_RESUME_SIZE_BYTES,
+                QUEUE_FLOW_CONTROL_SIZE_BYTES,
+                MESSAGE_GROUP_SHARED_GROUPS,
+                MESSAGE_GROUP_KEY,
+                ALTERNATE_EXCHANGE)));
+
+        LegacyQueue(final LegacyManagementController managementController,
+                    final LegacyConfiguredObject nextVersionQueue)
+        {
+            super(managementController, nextVersionQueue, QueueController.TYPE);
+        }
+
+        @Override
+        public Collection<String> getAttributeNames()
+        {
+            return Stream.concat(super.getAttributeNames().stream(),
+                                 MOVED_ATTRIBUTES.stream()).collect(Collectors.toSet());
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Collection<LegacyConfiguredObject> getChildren(final String category)
+        {
+            if (BindingController.TYPE.equals(category))
+            {
+                String queueName = (String) getAttribute(NAME);
+                Collection<LegacyConfiguredObject> exchanges =
+                        getNextVersionLegacyConfiguredObject().getParent(VirtualHostController.TYPE)
+                                                              .getChildren(ExchangeController.TYPE);
+
+                List<LegacyConfiguredObject> bindingObjects = new ArrayList<>();
+                for (LegacyConfiguredObject exchange : exchanges)
+                {
+                    Object bindings = exchange.getAttribute("bindings");
+                    if (bindings instanceof Collection)
+                    {
+                        Collection<?> exchangeBindings = (Collection<?>) bindings;
+                        exchangeBindings.stream()
+                                        .map(Binding.class::cast)
+                                        .filter(i -> i.getDestination().equals(queueName))
+                                        .map(i -> new BindingController.LegacyBinding(getManagementController(),
+                                                                                      exchange,
+                                                                                      getNextVersionLegacyConfiguredObject(),
+                                                                                      i.getBindingKey(),
+                                                                                      i.getArguments()))
+                                        .forEach(bindingObjects::add);
+                    }
+                }
+                return bindingObjects;
+            }
+            return super.getChildren(category);
+        }
+
+        protected Object getAttributeInternal(final String name, boolean isActual)
+        {
+            if (QUEUE_FLOW_CONTROL_SIZE_BYTES.equals(name))
+            {
+                final Object overflowPolicy = getAttribute("overflowPolicy", isActual);
+                if (overflowPolicy != null)
+                {
+                    final Object maximumQueueDepthBytes = getAttribute("maximumQueueDepthBytes", isActual);
+                    if ("PRODUCER_FLOW_CONTROL".equals(String.valueOf(overflowPolicy))
+                        && maximumQueueDepthBytes != null)
+                    {
+                        return maximumQueueDepthBytes;
+                    }
+                }
+                return null;
+            }
+            else if (QUEUE_FLOW_RESUME_SIZE_BYTES.equals(name))
+            {
+                final Object overflowPolicy = getAttribute("overflowPolicy", isActual);
+                final Object maximumQueueDepthBytes = getAttribute("maximumQueueDepthBytes", isActual);
+                if ("PRODUCER_FLOW_CONTROL".equals(String.valueOf(overflowPolicy)) && maximumQueueDepthBytes != null)
+                {
+                    final long queueFlowControlSizeBytesValue = ConverterHelper.toLong(maximumQueueDepthBytes);
+                    if (queueFlowControlSizeBytesValue > 0)
+                    {
+                        int queueFlowResumeLimit = 80;
+
+                        @SuppressWarnings("unchecked")
+                        Map<String, String> context = (Map<String, String>) super.getAttribute(CONTEXT);
+                        if (context != null)
+                        {
+                            queueFlowResumeLimit = ConverterHelper.toInt(context.get("queue.queueFlowResumeLimit"));
+                            if (queueFlowResumeLimit == 0)
+                            {
+                                queueFlowResumeLimit = 80;
+                            }
+                        }
+                        return Math.round(queueFlowControlSizeBytesValue * ((double) queueFlowResumeLimit) / 100.0);
+                    }
+                }
+                return null;
+            }
+            else if (MESSAGE_GROUP_SHARED_GROUPS.equals(name))
+            {
+                Object messageGroupType = getAttribute("messageGroupType", isActual);
+                if (messageGroupType != null)
+                {
+                    String type = String.valueOf(messageGroupType);
+                    return "SHARED_GROUPS".equals(type);
+                }
+                return null;
+            }
+            else if (MESSAGE_GROUP_KEY.equals(name))
+            {
+                Object messageGroupKeyOverride = getAttribute("messageGroupKeyOverride", isActual);
+                Object messageGroupType = getAttribute("messageGroupType", isActual);
+                if (messageGroupType != null)
+                {
+                    return messageGroupKeyOverride == null ? "JMSXGroupId" : messageGroupKeyOverride;
+                }
+                return null;
+            }
+
+            return super.getAttributeInternal(name, isActual);
+        }
+
+        @Override
+        public boolean isSecureAttribute(final String name)
+        {
+             if (MOVED_ATTRIBUTES.contains(name))
+             {
+                 return false;
+             }
+             return super.isSecureAttribute(name);
+        }
+
+        @Override
+        public boolean isOversizedAttribute(final String name)
+        {
+            if (MOVED_ATTRIBUTES.contains(name))
+            {
+                return false;
+            }
+            return super.isOversizedAttribute(name);
+        }
+    }
+}
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/SessionController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/SessionController.java
new file mode 100644
index 0000000..5177b1e
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/SessionController.java
@@ -0,0 +1,111 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import org.apache.qpid.server.management.plugin.controller.GenericLegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.management.plugin.controller.TypeController;
+
+public class SessionController extends LegacyCategoryController
+{
+    public static final String TYPE = "Session";
+
+    SessionController(final LegacyManagementController legacyManagementController,
+                      final Set<TypeController> typeControllers)
+    {
+        super(legacyManagementController,
+              TYPE,
+              new String[]{LegacyCategoryControllerFactory.CATEGORY_CONNECTION},
+              null,
+              typeControllers);
+    }
+
+    @Override
+    protected LegacyConfiguredObject convertNextVersionLegacyConfiguredObject(final LegacyConfiguredObject object)
+    {
+        return new LegacySession(getManagementController(), object);
+    }
+
+    public static class LegacySession extends GenericLegacyConfiguredObject
+    {
+        LegacySession(final LegacyManagementController managementController,
+                      final LegacyConfiguredObject nextVersionLegacyConfiguredObject)
+        {
+            super(managementController, nextVersionLegacyConfiguredObject, SessionController.TYPE);
+        }
+
+        @Override
+        @SuppressWarnings("unchecked")
+        public Collection<LegacyConfiguredObject> getChildren(final String category)
+        {
+            if (ConsumerController.TYPE.equalsIgnoreCase(category))
+            {
+                final LegacyConfiguredObject nextVersionSession = getNextVersionLegacyConfiguredObject();
+                final LegacyConfiguredObject connection =
+                        nextVersionSession.getParent(LegacyCategoryControllerFactory.CATEGORY_CONNECTION);
+                final LegacyConfiguredObject vh = connection.getParent(VirtualHostController.TYPE);
+                final UUID sessionID = (UUID) getAttribute(ID);
+                final UUID connectionID = (UUID) connection.getAttribute(ID);
+                final List<LegacyConfiguredObject> consumers = new ArrayList<>();
+                final Collection<LegacyConfiguredObject> queues = vh.getChildren(QueueController.TYPE);
+                if (queues != null)
+                {
+                    queues.forEach(q -> {
+                        final Collection<LegacyConfiguredObject> queueConsumers =
+                                q.getChildren(ConsumerController.TYPE);
+                        if (queueConsumers != null)
+                        {
+                            queueConsumers.stream()
+                                          .filter(c -> sameSession(c, sessionID, connectionID))
+                                          .map(c -> getManagementController().convertFromNextVersion(c))
+                                          .forEach(consumers::add);
+                        }
+                    });
+                }
+                return consumers;
+            }
+            return super.getChildren(category);
+        }
+
+        private boolean sameSession(final LegacyConfiguredObject consumer,
+                                    final UUID sessionID,
+                                    final UUID connectionID)
+        {
+            LegacyConfiguredObject session = (LegacyConfiguredObject) consumer.getAttribute("session");
+            if (session != null)
+            {
+                if (sessionID.equals(session.getAttribute(ID)))
+                {
+                    LegacyConfiguredObject con = session.getParent(LegacyCategoryControllerFactory.CATEGORY_CONNECTION);
+                    return con != null && connectionID.equals(con.getAttribute(ID));
+                }
+            }
+            return false;
+        }
+    }
+}
\ No newline at end of file
diff --git a/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/VirtualHostController.java b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/VirtualHostController.java
new file mode 100644
index 0000000..85904d0
--- /dev/null
+++ b/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/VirtualHostController.java
@@ -0,0 +1,130 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import static org.apache.qpid.server.management.plugin.ManagementException.createGoneManagementException;
+import static org.apache.qpid.server.management.plugin.controller.GenericLegacyConfiguredObject.CONTEXT;
+
+import java.util.Collection;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.management.plugin.controller.GenericLegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.management.plugin.controller.TypeController;
+import org.apache.qpid.server.model.ConfiguredObject;
+
+class VirtualHostController extends LegacyCategoryController
+{
+
+    public static final String TYPE = "VirtualHost";
+
+    VirtualHostController(final LegacyManagementController legacyManagementController,
+                          final Set<TypeController> typeControllers)
+    {
+        super(legacyManagementController,
+              TYPE,
+              new String[]{LegacyCategoryControllerFactory.CATEGORY_VIRTUAL_HOST_NODE},
+              "ProvidedStore",
+              typeControllers);
+    }
+
+    @Override
+    public LegacyConfiguredObject convertNextVersionLegacyConfiguredObject(final LegacyConfiguredObject object)
+    {
+        return new VirtualHostController.LegacyVirtualHost(getManagementController(), object);
+    }
+
+    @Override
+    @SuppressWarnings("unchecked")
+    public Map<String, Object> convertAttributesToNextVersion(final ConfiguredObject<?> root,
+                                                              final List<String> path,
+                                                              final Map<String, Object> attributes)
+    {
+
+        final Map<String, String> context = (Map<String, String>) attributes.get(CONTEXT);
+
+        if (attributes.containsKey(LegacyVirtualHost.QUEUE_DEAD_LETTER_QUEUE_ENABLED)
+            || (context != null && context.containsKey("queue.deadLetterQueueEnabled")))
+        {
+            final Map<String, Object> converted = new LinkedHashMap<>(attributes);
+            converted.remove("queue_deadLetterQueueEnabled");
+            if (context != null)
+            {
+                final Map<String, String> convertedContext = new LinkedHashMap<>(context);
+                converted.put("context", convertedContext);
+                convertedContext.remove("queue.deadLetterQueueEnabled");
+            }
+
+            return converted;
+        }
+        return attributes;
+    }
+
+    public static class LegacyVirtualHost extends GenericLegacyConfiguredObject
+    {
+        static final String QUEUE_DEAD_LETTER_QUEUE_ENABLED = "queue_deadLetterQueueEnabled";
+        private static final String MODEL_VERSION = "modelVersion";
+
+        LegacyVirtualHost(final LegacyManagementController managementController,
+                          final LegacyConfiguredObject nextVersionLegacyConfiguredObject)
+        {
+            super(managementController, nextVersionLegacyConfiguredObject, VirtualHostController.TYPE);
+        }
+
+        @Override
+        public Collection<String> getAttributeNames()
+        {
+
+            return super.getAttributeNames();
+        }
+
+        @Override
+        public Object getAttribute(final String name)
+        {
+            if (MODEL_VERSION.equals(name))
+            {
+                return getManagementController().getVersion();
+            }
+            else if (QUEUE_DEAD_LETTER_QUEUE_ENABLED.equals(name))
+            {
+                return false;
+            }
+            return super.getAttribute(name);
+        }
+
+        @Override
+        public ManagementResponse invoke(final String operation,
+                                         final Map<String, Object> parameters,
+                                         final boolean isSecure)
+        {
+            if ("resetStatistics".equalsIgnoreCase(operation))
+            {
+                throw createGoneManagementException("Method 'resetStatistics' was removed");
+            }
+            return super.invoke(operation, parameters, isSecure);
+        }
+    }
+}
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/LegacyManagementControllerTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/LegacyManagementControllerTest.java
new file mode 100644
index 0000000..50a8815
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/LegacyManagementControllerTest.java
@@ -0,0 +1,138 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.controller.CategoryController;
+import org.apache.qpid.server.management.plugin.controller.CategoryControllerFactory;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.TypeController;
+import org.apache.qpid.server.management.plugin.controller.TypeControllerFactory;
+import org.apache.qpid.server.management.plugin.controller.v6_1.category.BrokerController;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class LegacyManagementControllerTest extends UnitTestBase
+{
+
+    private LegacyManagementController _controller;
+    private ManagementController _nextVersionManagementController;
+
+    @Before
+    public void setUp()
+    {
+        _nextVersionManagementController = mock(ManagementController.class);
+        _controller = new LegacyManagementController(_nextVersionManagementController);
+        _controller.initialize();
+    }
+
+    @Test
+    public void convertQueryParameters()
+    {
+        final Map<String, List<String>> parameters = Collections.singletonMap("actuals", Collections.singletonList("true"));
+        final Map<String, List<String>> converted = _controller.convertQueryParameters(parameters);
+        assertThat(converted, is(notNullValue()));
+        assertThat(converted.get("excludeInheritedContext"), is(equalTo(Collections.singletonList("true"))));
+    }
+
+    @Test
+    public void formatConfiguredObject()
+    {
+        final String objectName = "test-object";
+        final String hostName = "test-vhn";
+        final Map<String, List<String>> parameters = Collections.emptyMap();
+        final LegacyConfiguredObject object = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject vhn = mock(LegacyConfiguredObject.class);
+        when(object.getAttributeNames()).thenReturn(Arrays.asList(LegacyConfiguredObject.NAME,
+                                                                  LegacyConfiguredObject.TYPE));
+        when(object.getAttribute(LegacyConfiguredObject.NAME)).thenReturn(objectName);
+        when(object.getAttribute(LegacyConfiguredObject.TYPE)).thenReturn("Broker");
+        when(object.getCategory()).thenReturn("Broker");
+        when(object.getChildren("VirtualHostNode")).thenReturn(Collections.singletonList(vhn));
+        when(vhn.getAttributeNames()).thenReturn(Arrays.asList(LegacyConfiguredObject.NAME,
+                                                               LegacyConfiguredObject.TYPE));
+        when(vhn.getAttribute(LegacyConfiguredObject.NAME)).thenReturn(hostName);
+        when(vhn.getAttribute(LegacyConfiguredObject.TYPE)).thenReturn("VirtualHostNode");
+        when(vhn.getCategory()).thenReturn("VirtualHostNode");
+
+        Object data = _controller.formatConfiguredObject(object, parameters, true);
+
+        assertThat(data, is(instanceOf(Map.class)));
+        Map<?, ?> formatted = (Map<?, ?>) data;
+
+        assertThat(formatted.get(LegacyConfiguredObject.NAME), is(equalTo(objectName)));
+        assertThat(formatted.get(LegacyConfiguredObject.TYPE), is(equalTo("Broker")));
+
+        Object vhns = formatted.get("virtualhostnodes");
+        assertThat(vhns, is(instanceOf(Collection.class)));
+
+        Collection<?> nodes = (Collection<?>)vhns;
+
+        assertThat(nodes.size(), is(equalTo(1)));
+
+        Object node = nodes.iterator().next();
+        assertThat(node, is(instanceOf(Map.class)));
+        Map<?, ?> formattedNode = (Map<?, ?>) node;
+
+        assertThat(formattedNode.get(LegacyConfiguredObject.NAME), is(equalTo(hostName)));
+        assertThat(formattedNode.get(LegacyConfiguredObject.TYPE), is(equalTo("VirtualHostNode")));
+    }
+
+    @Test
+    public void get()
+    {
+        final List<String> path = Collections.emptyList();
+        final LegacyConfiguredObject object = mock(LegacyConfiguredObject.class);
+        final Map<String, List<String>> parameters = Collections.emptyMap();
+
+        final ConfiguredObject<?> root = mock(ConfiguredObject.class);
+        when(_nextVersionManagementController.get(eq(root), eq(BrokerController.TYPE), eq(path), any())).thenReturn(object);
+        final Object result = _controller.get(root, BrokerController.TYPE, path, parameters);
+        assertThat(result, is(instanceOf(Collection.class)));
+        Collection data = (Collection) result;
+        assertThat(data.size(), is(equalTo(1)));
+        Object obj = data.iterator().next();
+        assertThat(obj, is(instanceOf(LegacyConfiguredObject.class)));
+
+        assertThat(((LegacyConfiguredObject)obj).getCategory(), is(equalTo(BrokerController.TYPE)));
+    }
+
+}
\ No newline at end of file
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/BindingControllerTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/BindingControllerTest.java
new file mode 100644
index 0000000..0051b60
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/BindingControllerTest.java
@@ -0,0 +1,312 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.ManagementException;
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.management.plugin.ResponseType;
+import org.apache.qpid.server.management.plugin.controller.ControllerManagementResponse;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class BindingControllerTest extends UnitTestBase
+{
+    private LegacyManagementController _managementController;
+    private LegacyManagementController _nextVersionManagementController;
+    private BindingController _controller;
+    private ConfiguredObject<?> _root;
+
+    @Before
+    public void setUp()
+    {
+        _managementController = mock(LegacyManagementController.class);
+        _nextVersionManagementController = mock(LegacyManagementController.class);
+        when(_managementController.getNextVersionManagementController()).thenReturn(_nextVersionManagementController);
+        _controller = new BindingController(_managementController);
+        _root = mock(ConfiguredObject.class);
+    }
+
+    @Test
+    public void getCategory()
+    {
+        assertThat(_controller.getCategory(), is(equalTo("Binding")));
+    }
+
+    @Test
+    public void getNextVersionCategory()
+    {
+        assertThat(_controller.getNextVersionCategory(), is(equalTo(null)));
+    }
+
+    @Test
+    public void getDefaultType()
+    {
+        assertThat(_controller.getDefaultType(), is(equalTo(null)));
+    }
+
+    @Test
+    public void getParentCategories()
+    {
+        assertThat(_controller.getParentCategories(), is(equalTo(new String[]{"Exchange", "Queue"})));
+    }
+
+    @Test
+    public void getManagementController()
+    {
+        assertThat(_controller.getManagementController(), is(equalTo(_managementController)));
+    }
+
+    @Test
+    public void get()
+    {
+        final List<String> path = Arrays.asList("my-vhn", "my-vh", "my-exchange", "my-queue", "my-binding");
+        final Map<String, List<String>> parameters =
+                Collections.singletonMap("actuals", Collections.singletonList("true"));
+
+        final List<String> hierarchy = Arrays.asList("virtualhostnode", "virtualhost", "exchange", "queue", "binding");
+        when(_managementController.getCategoryHierarchy(_root, "Binding")).thenReturn(hierarchy);
+
+        final LegacyConfiguredObject exchange1 = mock(LegacyConfiguredObject.class);
+        when(exchange1.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("foo");
+        when(exchange1.getCategory()).thenReturn("Exchange");
+
+        final LegacyConfiguredObject exchange2 = mock(LegacyConfiguredObject.class);
+        when(exchange2.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-exchange");
+        when(exchange2.getCategory()).thenReturn("Exchange");
+        final LegacyConfiguredObject vh = mock(LegacyConfiguredObject.class);
+        when(exchange2.getParent("VirtualHost")).thenReturn(vh);
+        final LegacyConfiguredObject queue = mock(LegacyConfiguredObject.class);
+        when(queue.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-queue");
+        final Collection<LegacyConfiguredObject> queues = Collections.singletonList(queue);
+        when(vh.getChildren("Queue")).thenReturn(queues);
+        final Binding binding = mock(Binding.class);
+        when(binding.getName()).thenReturn("my-binding");
+        when(binding.getDestination()).thenReturn("my-queue");
+        when(binding.getBindingKey()).thenReturn("my-binding");
+        final Collection<Binding> bindings = Collections.singletonList(binding);
+        when(exchange2.getAttribute("bindings")).thenReturn(bindings);
+        final Collection<LegacyConfiguredObject> exchanges = Arrays.asList(exchange1, exchange2);
+
+        doReturn(exchanges).when(_nextVersionManagementController).get(any(), eq("exchange"), any(), any());
+
+        final Object readResult = _controller.get(_root, path, parameters);
+        assertThat(readResult, is(instanceOf(Collection.class)));
+
+        final Collection<?> exchangeBindings = (Collection<?>) readResult;
+        assertThat(exchangeBindings.size(), is(equalTo(1)));
+
+        final Object object = exchangeBindings.iterator().next();
+        assertThat(object, is(instanceOf(LegacyConfiguredObject.class)));
+
+        final LegacyConfiguredObject bindingObject = (LegacyConfiguredObject) object;
+        assertThat(bindingObject.getAttribute(LegacyConfiguredObject.NAME), is(equalTo("my-binding")));
+    }
+
+    @Test
+    public void createOrUpdate()
+    {
+        final List<String> path = Arrays.asList("my-vhn", "my-vh", "my-exchange");
+        final Map<String, Object> attributes = new HashMap<>();
+        attributes.put("name", "my-binding");
+        attributes.put("queue", "my-queue");
+
+        final List<String> hierarchy = Arrays.asList("virtualhostnode", "virtualhost", "exchange", "queue", "binding");
+        doReturn(hierarchy).when(_managementController).getCategoryHierarchy(_root, "Binding");
+
+        final LegacyConfiguredObject exchange = mock(LegacyConfiguredObject.class);
+        when(exchange.getCategory()).thenReturn("Exchange");
+        when(exchange.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-exchange");
+
+        final ManagementResponse bindingResult = new ControllerManagementResponse(ResponseType.DATA, Boolean.TRUE);
+        when(exchange.invoke(eq("bind"), any(), eq(true))).thenReturn(bindingResult);
+
+        final LegacyConfiguredObject queue = mock(LegacyConfiguredObject.class);
+        when(queue.getCategory()).thenReturn("Queue");
+        when(queue.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-queue");
+
+        doReturn(exchange).when(_nextVersionManagementController).get(any(), eq("exchange"), any(), any());
+        doReturn(queue).when(_nextVersionManagementController).get(any(), eq("queue"), any(), any());
+        when(_managementController.convertFromNextVersion(exchange)).thenReturn(exchange);
+        when(_managementController.convertFromNextVersion(queue)).thenReturn(queue);
+
+        final LegacyConfiguredObject binding = _controller.createOrUpdate(_root, path, attributes, true);
+        assertThat(binding, is(notNullValue()));
+
+        assertThat(binding.getAttribute(LegacyConfiguredObject.NAME), is(equalTo("my-binding")));
+
+        Object queueObject = binding.getAttribute("queue");
+        Object exchangeObject = binding.getAttribute("exchange");
+
+        assertThat(queueObject, is(instanceOf(LegacyConfiguredObject.class)));
+        assertThat(exchangeObject, is(instanceOf(LegacyConfiguredObject.class)));
+
+        assertThat(((LegacyConfiguredObject) queueObject).getAttribute(LegacyConfiguredObject.NAME),
+                   is(equalTo("my-queue")));
+        assertThat(((LegacyConfiguredObject) exchangeObject).getAttribute(LegacyConfiguredObject.NAME),
+                   is(equalTo("my-exchange")));
+    }
+
+    @Test
+    public void delete()
+    {
+        final List<String> path = Arrays.asList("my-vhn", "my-vh", "my-exchange", "my-queue", "my-binding");
+
+        final List<String> hierarchy = Arrays.asList("virtualhostnode", "virtualhost", "exchange", "queue", "binding");
+        doReturn(hierarchy).when(_managementController).getCategoryHierarchy(_root, "Binding");
+
+
+        final LegacyConfiguredObject exchange = mock(LegacyConfiguredObject.class);
+        when(exchange.getCategory()).thenReturn("Exchange");
+        when(exchange.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-exchange");
+
+        final ManagementResponse unbindingResult = new ControllerManagementResponse(ResponseType.DATA, Boolean.TRUE);
+        when(exchange.invoke(eq("unbind"), any(), eq(true))).thenReturn(unbindingResult);
+
+        doReturn(exchange).when(_nextVersionManagementController).get(any(), eq("exchange"), any(), any());
+
+        int result = _controller.delete(_root, path, Collections.emptyMap());
+
+        assertThat(result, is(equalTo(1)));
+        verify(exchange).invoke(eq("unbind"), any(), eq(true));
+    }
+
+    @Test
+    public void invoke()
+    {
+        final List<String> path = Arrays.asList("my-vhn", "my-vh", "my-exchange", "my-queue", "my-binding");
+        final String operationName = "getStatistics";
+        final Map<String, Object> parameters = Collections.emptyMap();
+
+
+
+        final List<String> hierarchy = Arrays.asList("virtualhostnode", "virtualhost", "exchange", "queue", "binding");
+        when(_managementController.getCategoryHierarchy(_root, "Binding")).thenReturn(hierarchy);
+
+
+        final LegacyConfiguredObject exchange = mock(LegacyConfiguredObject.class);
+        when(exchange.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-exchange");
+        when(exchange.getCategory()).thenReturn("Exchange");
+        final LegacyConfiguredObject vh = mock(LegacyConfiguredObject.class);
+        when(exchange.getParent("VirtualHost")).thenReturn(vh);
+        final LegacyConfiguredObject queue = mock(LegacyConfiguredObject.class);
+        when(queue.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-queue");
+        final Collection<LegacyConfiguredObject> queues = Collections.singletonList(queue);
+        when(vh.getChildren("Queue")).thenReturn(queues);
+        final Binding binding = mock(Binding.class);
+        when(binding.getName()).thenReturn("my-binding");
+        when(binding.getDestination()).thenReturn("my-queue");
+        when(binding.getBindingKey()).thenReturn("my-binding");
+        final Collection<Binding> bindings = Collections.singletonList(binding);
+        when(exchange.getAttribute("bindings")).thenReturn(bindings);
+        final Collection<LegacyConfiguredObject> exchanges = Collections.singletonList(exchange);
+
+        doReturn(exchanges).when(_nextVersionManagementController).get(any(), eq("exchange"), any(), any());
+
+        final ManagementResponse result = _controller.invoke(_root, path, operationName, parameters, true, true);
+
+        assertThat(result, is(notNullValue()));
+        assertThat(result.getResponseCode(), is(equalTo(200)));
+        assertThat(result.getBody(), is(notNullValue()));
+        assertThat(result.getBody(), is(equalTo(Collections.emptyMap())));
+    }
+
+    @Test
+    public void getPreferences()
+    {
+        final List<String> path = Arrays.asList("vhn", "vh", "exchange", "queue", "binding");
+        final Map<String, List<String>> parameters = Collections.emptyMap();
+        try
+        {
+            _controller.getPreferences(_root, path, parameters);
+            fail("Binding preferences are unknown");
+        }
+        catch (ManagementException e)
+        {
+            // pass
+        }
+    }
+
+    @Test
+    public void setPreferences()
+    {
+        final List<String> path = Arrays.asList("vhn", "vh", "exchange", "queue", "binding");
+        final Map<String, List<String>> parameters = Collections.emptyMap();
+        try
+        {
+            _controller.setPreferences(_root,
+                                       path,
+                                       Collections.singletonMap("Binding-Preferences",
+                                                                Collections.singleton(Collections.singletonMap("value",
+                                                                                                               "foo"))),
+                                       parameters,
+                                       true);
+            fail("Binding preferences are unknown");
+        }
+        catch (ManagementException e)
+        {
+            // pass
+        }
+    }
+
+    @Test
+    public void deletePreferences()
+    {
+        final List<String> path = Arrays.asList("vhn", "vh", "exchange", "queue", "binding");
+        final Map<String, List<String>> parameters = Collections.emptyMap();
+        try
+        {
+            _controller.deletePreferences(_root,
+                                          path,
+                                          parameters);
+            fail("Binding preferences are unknown");
+        }
+        catch (ManagementException e)
+        {
+            // pass
+        }
+    }
+}
\ No newline at end of file
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/BrokerControllerTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/BrokerControllerTest.java
new file mode 100644
index 0000000..275567e
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/BrokerControllerTest.java
@@ -0,0 +1,104 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.controller.CategoryController;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class BrokerControllerTest extends UnitTestBase
+{
+    private LegacyManagementController _legacyVersionManagementController;
+    private String MODEL_VERSION = "6.1";
+
+    @Before
+    public void setUp()
+    {
+        _legacyVersionManagementController = mock(LegacyManagementController.class);
+        when(_legacyVersionManagementController.getVersion()).thenReturn(MODEL_VERSION);
+    }
+
+    @Test
+    public void convertNextVersionLegacyConfiguredObject()
+    {
+        final LegacyConfiguredObject object = mock(LegacyConfiguredObject.class);
+        when(object.getAttribute("modelVersion")).thenReturn("foo");
+        final Map<String, String> context = new HashMap<>();
+        context.put("qpid.port.sessionCountLimit", "512");
+        context.put("qpid.port.heartbeatDelay", "10000");
+        context.put("qpid.port.closeWhenNoRoute", "true");
+        when(object.getAttribute("context")).thenReturn(context);
+
+        final BrokerController controller =
+                new BrokerController(_legacyVersionManagementController, Collections.emptySet());
+        assertThat(controller.getCategory(), is(equalTo("Broker")));
+
+        final LegacyConfiguredObject converted = controller.convertFromNextVersion(object);
+        assertThat(converted.getAttribute("modelVersion"), is(equalTo(MODEL_VERSION)));
+        assertThat(converted.getAttribute("connection.sessionCountLimit"), is(equalTo(512)));
+        assertThat(converted.getAttribute("connection.heartBeatDelay"), is(equalTo(10000L)));
+        assertThat(converted.getAttribute("connection.closeWhenNoRoute"), is(equalTo(true)));
+    }
+
+
+    @Test
+    public void convertAttributesToNextVersion()
+    {
+        final Map<String, Object> attributes = new HashMap<>();
+        attributes.put("connection.sessionCountLimit", 512);
+        attributes.put("connection.heartBeatDelay", 10000L);
+        attributes.put("connection.closeWhenNoRoute", true);
+        attributes.put("statisticsReportingResetEnabled", true);
+        attributes.put("statisticsReportingEnabled", true);
+
+        final BrokerController controller =
+                new BrokerController(_legacyVersionManagementController, Collections.emptySet());
+        assertThat(controller.getCategory(), is(equalTo("Broker")));
+
+        final Map<String, Object> converted = controller.convertAttributesToNextVersion(mock(ConfiguredObject.class),
+                                                                                        Collections.emptyList(),
+                                                                                        attributes);
+        assertThat(converted.size(), is(equalTo(2)));
+        assertThat(converted.get("statisticsReportingEnabled"), is(equalTo(true)));
+
+        final Map<String, String> expectedContext = new HashMap<>();
+        expectedContext.put("qpid.port.sessionCountLimit", "512");
+        expectedContext.put("qpid.port.heartbeatDelay", "10000");
+        expectedContext.put("qpid.port.closeWhenNoRoute", "true");
+        assertThat(converted.get("context"), is(equalTo(expectedContext)));
+    }
+}
\ No newline at end of file
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/ConsumerControllerTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/ConsumerControllerTest.java
new file mode 100644
index 0000000..4df2929
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/ConsumerControllerTest.java
@@ -0,0 +1,317 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.ManagementException;
+import org.apache.qpid.server.management.plugin.ManagementResponse;
+import org.apache.qpid.server.management.plugin.ResponseType;
+import org.apache.qpid.server.management.plugin.controller.ControllerManagementResponse;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.server.model.Connection;
+import org.apache.qpid.server.model.Session;
+import org.apache.qpid.server.transport.AbstractAMQPConnection;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class ConsumerControllerTest extends UnitTestBase
+{
+    private LegacyManagementController _managementController;
+    private LegacyManagementController _nextVersionManagementController;
+    private ConsumerController _controller;
+    private ConfiguredObject<?> _root;
+
+    @Before
+    public void setUp()
+    {
+        _managementController = mock(LegacyManagementController.class);
+        _nextVersionManagementController = mock(LegacyManagementController.class);
+        when(_managementController.getNextVersionManagementController()).thenReturn(_nextVersionManagementController);
+        _controller = new ConsumerController(_managementController);
+        _root = mock(ConfiguredObject.class);
+    }
+    @Test
+    public void getCategory()
+    {
+        assertThat(_controller.getCategory(), is(equalTo("Consumer")));
+    }
+
+    @Test
+    public void getNextVersionCategory()
+    {
+        assertThat(_controller.getNextVersionCategory(), is(equalTo("Consumer")));
+    }
+
+    @Test
+    public void getDefaultType()
+    {
+        assertThat(_controller.getDefaultType(), is(equalTo(null)));
+    }
+
+    @Test
+    public void getParentCategories()
+    {
+        assertThat(_controller.getParentCategories(), is(equalTo(new String[]{"Session", "Queue"})));
+    }
+
+    @Test
+    public void getManagementController()
+    {
+        assertThat(_controller.getManagementController(), is(equalTo(_managementController)));
+    }
+
+    @Test
+    public void get()
+    {
+        final List<String> path = Arrays.asList("my-vhn", "my-vh", "my-session", "my-queue", "my-consumer");
+        final Map<String, List<String>> parameters =
+                Collections.singletonMap("actuals", Collections.singletonList("true"));
+
+        final List<String> hierarchy = Arrays.asList("virtualhostnode", "virtualhost", "session", "queue", "consumer");
+        when(_managementController.getCategoryHierarchy(_root, "Consumer")).thenReturn(hierarchy);
+
+        final LegacyConfiguredObject session = mock(LegacyConfiguredObject.class);
+        when(session.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-session");
+        when(session.getCategory()).thenReturn("Session");
+
+        final LegacyConfiguredObject consumer = mock(LegacyConfiguredObject.class);
+        when(consumer.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-consumer");
+        when(consumer.getAttribute("session")).thenReturn(session);
+        final Collection<LegacyConfiguredObject> consumers = Collections.singletonList(consumer);
+
+        final LegacyConfiguredObject queue1 = mock(LegacyConfiguredObject.class);
+        when(queue1.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-queue1");
+        final LegacyConfiguredObject queue2 = mock(LegacyConfiguredObject.class);
+        when(queue2.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-queue");
+        when(queue2.getChildren(ConsumerController.TYPE)).thenReturn(consumers);
+
+        final Collection<LegacyConfiguredObject> queues = Arrays.asList(queue1, queue2);
+
+        doReturn(queues).when(_nextVersionManagementController)
+                       .get(eq(_root),
+                            eq("Queue"),
+                            eq(Arrays.asList("my-vhn", "my-vh")),
+                            eq(Collections.emptyMap()));
+
+        final Object result = _controller.get(_root, path, parameters);
+        assertThat(result, is(instanceOf(Collection.class)));
+
+        Collection<?> consumerItems = (Collection<?>)result;
+        assertThat(consumerItems.size(), is(equalTo(1)));
+
+        final Object object = consumerItems.iterator().next();
+        assertThat(object, is(instanceOf(LegacyConfiguredObject.class)));
+
+        final LegacyConfiguredObject consumerObject = (LegacyConfiguredObject) object;
+        assertThat(consumerObject.getAttribute(LegacyConfiguredObject.NAME), is(equalTo("my-consumer")));
+        assertThat(consumerObject.getCategory(), is(equalTo("Consumer")));
+    }
+
+    @Test
+    public void delete()
+    {
+        final List<String> path = Arrays.asList("my-vhn", "my-vh",  "my-queue", "my-consumer");
+        final Map<String, List<String>> parameters = Collections.emptyMap();
+        try
+        {
+            _controller.delete(_root, path, parameters);
+            fail("Consumer cannot be deleted from REST");
+        }
+        catch (ManagementException e)
+        {
+            // pass
+        }
+    }
+
+    @Test
+    public void createOrUpdate()
+    {
+        final List<String> path = Arrays.asList("my-vhn", "my-vh",  "my-queue", "my-consumer");
+        final Map<String, Object> attributes = Collections.singletonMap(LegacyConfiguredObject.NAME, "my-consumer" );
+        try
+        {
+            _controller.createOrUpdate(_root, path, attributes, true);
+            fail("Consumer cannot be created from REST");
+        }
+        catch (ManagementException e)
+        {
+            // pass
+        }
+    }
+
+    @Test
+    public void invoke()
+    {
+        final List<String> path = Arrays.asList("my-vhn", "my-vh", "my-session", "my-queue", "my-consumer");
+        final List<String> hierarchy = Arrays.asList("virtualhostnode", "virtualhost", "session", "queue", "consumer");
+        when(_managementController.getCategoryHierarchy(_root, "Consumer")).thenReturn(hierarchy);
+
+        final LegacyConfiguredObject consumer = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject queue = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject session = mock(LegacyConfiguredObject.class);
+        when(queue.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-queue");
+        when(consumer.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-consumer");
+        when(consumer.getAttribute("session")).thenReturn(session);
+        when(session.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-session");
+
+        final Object stats = mock(Object.class);
+        final ManagementResponse statistics = new ControllerManagementResponse(ResponseType.DATA, stats);
+        when(consumer.invoke(eq("getStatistics"), eq(Collections.emptyMap()), eq(false))).thenReturn(statistics);
+        final Collection<LegacyConfiguredObject> consumers = Collections.singletonList(consumer);
+        when(queue.getChildren(ConsumerController.TYPE)).thenReturn(consumers);
+
+        final Collection<LegacyConfiguredObject> queues = Collections.singletonList(queue);
+
+        doReturn(queues).when(_nextVersionManagementController)
+                        .get(eq(_root),
+                             eq("Queue"),
+                             eq(Arrays.asList("my-vhn", "my-vh")),
+                             eq(Collections.emptyMap()));
+
+        ManagementResponse response = _controller.invoke(_root, path, "getStatistics", Collections.emptyMap(), false, false);
+        assertThat(response, is(notNullValue()));
+        assertThat(response.getResponseCode(), is(equalTo(200)));
+        assertThat(response.getBody(), is(notNullValue()));
+        assertThat(response.getBody(), is(equalTo(stats)));
+    }
+
+    @Test
+    public void getPreferences()
+    {
+        final List<String> path = Arrays.asList("my-vhn", "my-vh",  "my-queue", "my-consumer");
+        final Map<String, List<String>> parameters = Collections.emptyMap();
+        try
+        {
+            _controller.getPreferences(_root, path, parameters);
+            fail("Consumer preferences are unknown");
+        }
+        catch (ManagementException e)
+        {
+            // pass
+        }
+    }
+
+    @Test
+    public void setPreferences()
+    {
+        final List<String> path = Arrays.asList("my-vhn", "my-vh",  "my-queue", "my-consumer");
+        final Map<String, List<String>> parameters = Collections.emptyMap();
+        try
+        {
+            _controller.setPreferences(_root,
+                                       path,
+                                       Collections.singletonMap("Consumer-Preferences",
+                                                                Collections.singleton(Collections.singletonMap("value",
+                                                                                                               "foo"))),
+                                       parameters,
+                                       true);
+            fail("Consumer preferences are unknown");
+        }
+        catch (ManagementException e)
+        {
+            // pass
+        }
+    }
+
+    @Test
+    public void deletePreferences()
+    {
+        final List<String> path = Arrays.asList("my-vhn", "my-vh",  "my-queue", "my-consumer");
+        final Map<String, List<String>> parameters = Collections.emptyMap();
+        try
+        {
+            _controller.deletePreferences(_root,
+                                          path,
+                                          parameters);
+            fail("Consumer preferences are unknown");
+        }
+        catch (ManagementException e)
+        {
+            // pass
+        }
+    }
+
+    @Test
+    public void convertFromNextVersion()
+    {
+        final LegacyConfiguredObject session = mock(LegacyConfiguredObject.class);
+        when(session.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-session");
+        when(session.getCategory()).thenReturn("Session");
+
+
+
+        final LegacyConfiguredObject queue1 = mock(LegacyConfiguredObject.class);
+        when(queue1.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-queue1");
+        final LegacyConfiguredObject queue2 = mock(LegacyConfiguredObject.class);
+        when(queue2.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("my-queue");
+
+
+
+        final LegacyConfiguredObject nextVersionConfiguredObject = mock(LegacyConfiguredObject.class);
+        when(nextVersionConfiguredObject.getAttribute("session")).thenReturn(session);
+        when(nextVersionConfiguredObject.getAttribute("queue")).thenReturn(queue2);
+        when(nextVersionConfiguredObject.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("test-consumer");
+        when(nextVersionConfiguredObject.getParent(eq("Queue"))).thenReturn(queue2);
+        final Collection<LegacyConfiguredObject> consumers = Collections.singletonList(nextVersionConfiguredObject);
+        when(queue2.getChildren(ConsumerController.TYPE)).thenReturn(consumers);
+
+        final LegacyConfiguredObject convertedSession = mock(LegacyConfiguredObject.class);
+        when(_managementController.convertFromNextVersion(session)).thenReturn(convertedSession);
+        final LegacyConfiguredObject convertedQueue = mock(LegacyConfiguredObject.class);
+        when(_managementController.convertFromNextVersion(queue2)).thenReturn(convertedQueue);
+        final LegacyConfiguredObject  converted = _controller.convertFromNextVersion(nextVersionConfiguredObject);
+
+        LegacyConfiguredObject sessionParent = converted.getParent("Session");
+        LegacyConfiguredObject queueParent = converted.getParent("Queue");
+
+        assertThat(sessionParent, is(equalTo(convertedSession)));
+        assertThat(queueParent, is(equalTo(convertedQueue)));
+
+        LegacyConfiguredObject sessionAttribute = (LegacyConfiguredObject)converted.getAttribute("session");
+        LegacyConfiguredObject queueAttribute = (LegacyConfiguredObject)converted.getAttribute("queue");
+
+        assertThat(sessionAttribute, is(equalTo(convertedSession)));
+        assertThat(queueAttribute, is(equalTo(convertedQueue)));
+
+    }
+}
\ No newline at end of file
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/DestinationControllerTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/DestinationControllerTest.java
new file mode 100644
index 0000000..4c76ccf
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/DestinationControllerTest.java
@@ -0,0 +1,135 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.mockingDetails;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.model.AlternateBinding;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class DestinationControllerTest extends UnitTestBase
+{
+    private LegacyManagementController _legacyVersionManagementController;
+    private ManagementController _nextVersionManagementController;
+
+    @Before
+    public void setUp()
+    {
+        _legacyVersionManagementController = mock(LegacyManagementController.class);
+        _nextVersionManagementController = mock(ManagementController.class);
+        when(_legacyVersionManagementController.getNextVersionManagementController()).thenReturn(
+                _nextVersionManagementController);
+    }
+
+    @Test
+    public void convertAttributesToNextVersion()
+    {
+        final String alternateExchangeName = "alternate";
+        final String queueName = "test";
+        final Map<String, Object> attributes = new HashMap<>();
+        attributes.put("alternateExchange", alternateExchangeName);
+        attributes.put(LegacyConfiguredObject.NAME, queueName);
+
+        final DestinationController controller =
+                new DestinationController(_legacyVersionManagementController,
+                                          "Queue",
+                                          new String[]{"VirtualHost"},
+                                          null,
+                                          Collections.emptySet());
+        assertThat(controller.getCategory(), is(equalTo("Queue")));
+        assertThat(controller.getParentCategories(), is(equalTo(new String[]{"VirtualHost"})));
+
+        final ConfiguredObject root = mock(ConfiguredObject.class);
+        final List<String> exchangePath = Arrays.asList("vhn", "vh");
+        final LegacyConfiguredObject exchange = mock(LegacyConfiguredObject.class);
+        when(exchange.getAttribute(LegacyConfiguredObject.NAME)).thenReturn(alternateExchangeName);
+        when(exchange.getCategory()).thenReturn(ExchangeController.TYPE);
+        final Collection<LegacyConfiguredObject> exchanges = Collections.singletonList(exchange);
+        when(_nextVersionManagementController.get(eq(root),
+                                                  eq(ExchangeController.TYPE),
+                                                  eq(exchangePath),
+                                                  eq(Collections.emptyMap()))).thenReturn(exchanges);
+
+        final Collection<String> hierarchy = Arrays.asList("virtualhostnode", "virtualhost", "exchange");
+        when(_nextVersionManagementController.getCategoryHierarchy(eq(root), eq(ExchangeController.TYPE))).thenReturn(hierarchy);
+        final List<String> path = Arrays.asList("vhn", "vh", queueName);
+        final Map<String, Object> converted = controller.convertAttributesToNextVersion(root,
+                                                                                        path,
+                                                                                        attributes);
+        assertThat(converted.size(), is(equalTo(2)));
+        assertThat(converted.get(LegacyConfiguredObject.NAME), is(equalTo(queueName)));
+        final Object alternateBinding = converted.get("alternateBinding");
+        assertThat(alternateBinding, is(notNullValue()));
+        assertThat(alternateBinding, is(instanceOf(Map.class)));
+
+        final Map<?, ?> alternateDestination = (Map<?, ?>) alternateBinding;
+        assertThat(alternateDestination.get("destination"), is(equalTo(alternateExchangeName)));
+        assertThat(alternateDestination.get("attributes"), is(equalTo(null)));
+    }
+
+    @Test
+    public void testLegacyDestination()
+    {
+        final String alternateExchangeName = "alt";
+        final LegacyConfiguredObject nextVersionDestination = mock(LegacyConfiguredObject.class);
+        final AlternateBinding alternateDestination = mock(AlternateBinding.class);
+        when(alternateDestination.getDestination()).thenReturn(alternateExchangeName);
+        when(nextVersionDestination.getAttribute("alternateBinding")).thenReturn(alternateDestination);
+
+        final LegacyConfiguredObject vh = mock(LegacyConfiguredObject.class);
+        when(nextVersionDestination.getParent(VirtualHostController.TYPE)).thenReturn(vh);
+        final LegacyConfiguredObject alternateExchange = mock(LegacyConfiguredObject.class);
+        when(alternateExchange.getCategory()).thenReturn(ExchangeController.TYPE);
+        when(alternateExchange.getAttribute(LegacyConfiguredObject.NAME)).thenReturn(alternateExchangeName);
+        final Collection<LegacyConfiguredObject> exchanges = Collections.singletonList(alternateExchange);
+        when(vh.getChildren(ExchangeController.TYPE)).thenReturn(exchanges);
+
+        final LegacyConfiguredObject converted = mock(LegacyConfiguredObject.class);
+        when(_legacyVersionManagementController.convertFromNextVersion(alternateExchange)).thenReturn(converted);
+
+        DestinationController.LegacyDestination destination = new DestinationController.LegacyDestination(_legacyVersionManagementController, nextVersionDestination, "Queue");
+
+
+        assertThat(destination.getAttribute("alternateExchange"), is(equalTo(converted)));
+    }
+}
\ No newline at end of file
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/ExchangeControllerTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/ExchangeControllerTest.java
new file mode 100644
index 0000000..13f3ee9
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/ExchangeControllerTest.java
@@ -0,0 +1,113 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.AlternateBinding;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class ExchangeControllerTest extends UnitTestBase
+{
+    private LegacyManagementController _legacyManagementController;
+
+    @Before
+    public void setUp()
+    {
+        _legacyManagementController = mock(LegacyManagementController.class);
+        final ManagementController nextVersionManagementController = mock(ManagementController.class);
+        when(_legacyManagementController.getNextVersionManagementController()).thenReturn(
+                nextVersionManagementController);
+    }
+
+    @Test
+    public void convertNextVersionLegacyConfiguredObject()
+    {
+        final ExchangeController exchangeController =
+                new ExchangeController(_legacyManagementController, Collections.emptySet());
+
+        final String exchangeName = "testExchange";
+        final String alternateExchangeName = "altExchange";
+        final String queueName = "testQueue";
+        final String bindingKey = "testBindingKey";
+
+        final LegacyConfiguredObject nextVersionExchange = mock(LegacyConfiguredObject.class);
+        final AlternateBinding alternateBinding = mock(AlternateBinding.class);
+        final Binding nextVersionBinding = mock(Binding.class);
+        final LegacyConfiguredObject nextVersionAlternateExchange = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject nextVersionVirtualHost = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject queue = mock(LegacyConfiguredObject.class);
+
+        when(alternateBinding.getDestination()).thenReturn(alternateExchangeName);
+
+        when(nextVersionExchange.getCategory()).thenReturn(ExchangeController.TYPE);
+        when(nextVersionExchange.getAttribute("alternateBinding")).thenReturn(alternateBinding);
+        when(nextVersionExchange.getAttribute(AbstractConfiguredObject.NAME)).thenReturn(exchangeName);
+        when(nextVersionExchange.getAttribute("bindings")).thenReturn(Collections.singletonList(nextVersionBinding));
+        when(nextVersionExchange.getParent(VirtualHostController.TYPE)).thenReturn(nextVersionVirtualHost);
+
+        when(nextVersionBinding.getDestination()).thenReturn(queueName);
+        when(nextVersionBinding.getBindingKey()).thenReturn(bindingKey);
+
+        when(nextVersionAlternateExchange.getCategory()).thenReturn(ExchangeController.TYPE);
+        when(nextVersionAlternateExchange.getAttribute(LegacyConfiguredObject.NAME)).thenReturn(alternateExchangeName);
+
+        when(nextVersionVirtualHost.getChildren(ExchangeController.TYPE)).thenReturn(Arrays.asList(nextVersionExchange,
+                nextVersionAlternateExchange));
+        when(nextVersionVirtualHost.getChildren(QueueController.TYPE)).thenReturn(Collections.singletonList(queue));
+
+        final LegacyConfiguredObject convertedExchange = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject convertedAltExchange = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject convertedQueue = mock(LegacyConfiguredObject.class);
+        when(_legacyManagementController.convertFromNextVersion(nextVersionExchange)).thenReturn(convertedExchange);
+        when(_legacyManagementController.convertFromNextVersion(nextVersionAlternateExchange)).thenReturn(convertedAltExchange);
+        when(_legacyManagementController.convertFromNextVersion(queue)).thenReturn(convertedQueue);
+
+        final LegacyConfiguredObject destination = exchangeController.convertFromNextVersion(nextVersionExchange);
+
+        assertThat(destination.getAttribute("alternateExchange"), is(equalTo(convertedAltExchange)));
+
+        final Collection<LegacyConfiguredObject> children = destination.getChildren(BindingController.TYPE);
+        assertThat(children.size(), is(equalTo(1)));
+
+        final LegacyConfiguredObject o = children.iterator().next();
+        assertThat(o.getCategory(), is(equalTo(BindingController.TYPE)));
+        assertThat(o.getAttribute(AbstractConfiguredObject.NAME), is(equalTo(bindingKey)));
+        assertThat(o.getAttribute("queue"), is(equalTo(convertedQueue)));
+        assertThat(o.getAttribute("exchange"), is(equalTo(convertedExchange)));
+    }
+}
\ No newline at end of file
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/LegacyCategoryControllerFactoryTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/LegacyCategoryControllerFactoryTest.java
new file mode 100644
index 0000000..db5f26d
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/LegacyCategoryControllerFactoryTest.java
@@ -0,0 +1,63 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.controller.CategoryController;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class LegacyCategoryControllerFactoryTest extends UnitTestBase
+{
+    private LegacyCategoryControllerFactory _factory;
+    private LegacyManagementController _nextVersionManagementController;
+
+    @Before
+    public void setUp()
+    {
+        _nextVersionManagementController = mock(LegacyManagementController.class);
+        _factory = new LegacyCategoryControllerFactory();
+    }
+
+    @Test
+    public void createController()
+    {
+        LegacyCategoryControllerFactory.SUPPORTED_CATEGORIES.forEach(category -> {
+            final CategoryController controller =
+                    _factory.createController(category, _nextVersionManagementController);
+            assertThat(controller.getCategory(), is(equalTo(category)));
+        });
+    }
+
+    @Test
+    public void getSupportedCategories()
+    {
+        assertThat(_factory.getSupportedCategories(),
+                   is(equalTo(LegacyCategoryControllerFactory.SUPPORTED_CATEGORIES)));
+    }
+}
\ No newline at end of file
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/LegacyCategoryControllerTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/LegacyCategoryControllerTest.java
new file mode 100644
index 0000000..8aa5b0a
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/LegacyCategoryControllerTest.java
@@ -0,0 +1,80 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.model.VirtualHostNode;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class LegacyCategoryControllerTest extends UnitTestBase
+{
+
+    private LegacyCategoryController _controller;
+
+    @Before
+    public void setUp()
+    {
+        final LegacyManagementController legacyManagementController = mock(LegacyManagementController.class);
+        final ManagementController nextVersionManagementController = mock(ManagementController.class);
+        when(legacyManagementController.getNextVersionManagementController()).thenReturn(
+                nextVersionManagementController);
+        _controller = new LegacyCategoryController(legacyManagementController,
+                                                   VirtualHostNode.TYPE,
+                                                   new String[]{BrokerController.TYPE},
+                                                   null,
+                                                   Collections.emptySet());
+    }
+
+
+    @Test
+    public void getParentCategories()
+    {
+        assertThat(_controller.getParentCategories(), is(equalTo(new String[]{BrokerController.TYPE})));
+    }
+
+    @Test
+    public void convertNextVersionLegacyConfiguredObject()
+    {
+        final LegacyConfiguredObject node = mock(LegacyConfiguredObject.class);
+        when(node.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("test");
+
+        final LegacyConfiguredObject converted =
+                _controller.convertNextVersionLegacyConfiguredObject(node);
+
+        assertThat(converted, is(notNullValue()));
+        assertThat(converted.getCategory(), is(equalTo(VirtualHostNode.TYPE)));
+        assertThat(converted.getAttribute(LegacyConfiguredObject.NAME), is(equalTo("test")));
+    }
+}
\ No newline at end of file
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/PortControllerTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/PortControllerTest.java
new file mode 100644
index 0000000..a915619
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/PortControllerTest.java
@@ -0,0 +1,113 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class PortControllerTest extends UnitTestBase
+{
+    private PortController _portController;
+
+    @Before
+    public void setUp()
+    {
+        final LegacyManagementController legacyManagementController = mock(LegacyManagementController.class);
+        final ManagementController nextVersionManagementController = mock(ManagementController.class);
+        when(legacyManagementController.getNextVersionManagementController()).thenReturn(
+                nextVersionManagementController);
+        _portController = new PortController(legacyManagementController, Collections.emptySet());
+    }
+
+    @Test
+    public void convertNextVersionLegacyConfiguredObject()
+    {
+        final LegacyConfiguredObject nextVersionPort = mock(LegacyConfiguredObject.class);
+        when(nextVersionPort.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("test");
+        when(nextVersionPort.getAttribute(LegacyConfiguredObject.TYPE)).thenReturn("HTTP");
+        Map<String, String> context = new HashMap<>();
+        context.put("qpid.port.http.acceptBacklog", "2000");
+        when(nextVersionPort.getAttribute(LegacyConfiguredObject.CONTEXT)).thenReturn(context);
+
+        final LegacyConfiguredObject converted =
+                _portController.convertNextVersionLegacyConfiguredObject(nextVersionPort);
+
+        assertThat(converted, is(notNullValue()));
+        assertThat(converted.getCategory(), is(equalTo(PortController.TYPE)));
+        assertThat(converted.getAttribute(LegacyConfiguredObject.NAME), is(equalTo("test")));
+        assertThat(converted.getAttribute(LegacyConfiguredObject.TYPE), is(equalTo("HTTP")));
+
+        Object contextObject = converted.getAttribute(LegacyConfiguredObject.CONTEXT);
+        assertThat(contextObject, is(instanceOf(Map.class)));
+
+        Map<?,?> convertedContext = (Map<?,?>)contextObject;
+        assertThat(convertedContext.get("port.http.maximumQueuedRequests"), is(equalTo("2000")));
+    }
+
+    @Test
+    public void convertAttributesToNextVersion()
+    {
+        Map<String, Object> attributes = new HashMap<>();
+        attributes.put(LegacyConfiguredObject.NAME, "test");
+        attributes.put(LegacyConfiguredObject.TYPE, "HTTP");
+        Map<String, String> context = new HashMap<>();
+        context.put("port.http.maximumQueuedRequests", "2000");
+        context.put("port.http.additionalInternalThreads", "10");
+        attributes.put(LegacyConfiguredObject.CONTEXT, context);
+
+        final ConfiguredObject<?> root = mock(ConfiguredObject.class);
+        final List<String> path = Collections.emptyList();
+        final Map<String, Object> converted = _portController.convertAttributesToNextVersion(root, path, attributes);
+
+        assertThat(converted, is(instanceOf(Map.class)));
+        assertThat(converted.get(LegacyConfiguredObject.NAME), is(equalTo("test")));
+        assertThat(converted.get(LegacyConfiguredObject.TYPE), is(equalTo("HTTP")));
+
+        Object contextObject = converted.get(LegacyConfiguredObject.CONTEXT);
+        assertThat(converted, is(instanceOf(Map.class)));
+
+        Map<?,?> convertedContext = (Map<?,?>)contextObject;
+
+        assertThat(convertedContext.get("qpid.port.http.acceptBacklog"), is(equalTo("2000")));
+        assertThat(convertedContext.containsKey("port.http.additionalInternalThreads"), is(equalTo(false)));
+
+
+    }
+}
\ No newline at end of file
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/QueueControllerTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/QueueControllerTest.java
new file mode 100644
index 0000000..0684636
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/QueueControllerTest.java
@@ -0,0 +1,161 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.model.AbstractConfiguredObject;
+import org.apache.qpid.server.model.AlternateBinding;
+import org.apache.qpid.server.model.Binding;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class QueueControllerTest extends UnitTestBase
+{
+    private LegacyManagementController _legacyVersionManagementController;
+    private QueueController _queueController;
+
+    @Before
+    public void setUp()
+    {
+        _legacyVersionManagementController = mock(LegacyManagementController.class);
+        final ManagementController nextVersionManagementController = mock(ManagementController.class);
+        when(_legacyVersionManagementController.getNextVersionManagementController()).thenReturn(
+                nextVersionManagementController);
+        _queueController = new QueueController(_legacyVersionManagementController, Collections.emptySet());
+    }
+
+    @Test
+    public void convertNextVersionLegacyConfiguredObject()
+    {
+        final String exchangeName = "testExchange";
+        final String alternateExchangeName = "altExchange";
+        final String queueName = "testQueue";
+        final String bindingKey = "testBindingKey";
+
+        final LegacyConfiguredObject nextVersionQueue = mock(LegacyConfiguredObject.class);
+        final Binding nextVersionBinding = mock(Binding.class);
+        final LegacyConfiguredObject nextVersionVirtualHost = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject nextVersionAlternateExchange = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject nextVersionExchange = mock(LegacyConfiguredObject.class);
+
+        final AlternateBinding alternateDestination = mock(AlternateBinding.class);
+        when(alternateDestination.getDestination()).thenReturn(alternateExchangeName);
+
+        when(nextVersionQueue.getCategory()).thenReturn(QueueController.TYPE);
+        when(nextVersionQueue.getParent(VirtualHostController.TYPE)).thenReturn(nextVersionVirtualHost);
+        when(nextVersionQueue.getAttribute("alternateBinding")).thenReturn(alternateDestination);
+        when(nextVersionQueue.getAttribute(AbstractConfiguredObject.NAME)).thenReturn(queueName);
+        when(nextVersionQueue.getAttribute("overflowPolicy")).thenReturn("PRODUCER_FLOW_CONTROL");
+        when(nextVersionQueue.getAttribute("maximumQueueDepthBytes")).thenReturn(10000L);
+        when(nextVersionQueue.getAttribute("context")).thenReturn(Collections.singletonMap("queue.queueFlowResumeLimit", "70"));
+        when(nextVersionQueue.getAttribute("messageGroupType")).thenReturn("SHARED_GROUPS");
+        when(nextVersionQueue.getAttribute("messageGroupKeyOverride")).thenReturn("test");
+
+        when(nextVersionBinding.getDestination()).thenReturn(queueName);
+        when(nextVersionBinding.getBindingKey()).thenReturn(bindingKey);
+
+        when(nextVersionExchange.getAttribute(AbstractConfiguredObject.NAME)).thenReturn(exchangeName);
+        when(nextVersionExchange.getCategory()).thenReturn(ExchangeController.TYPE);
+        when(nextVersionExchange.getAttribute("bindings")).thenReturn(Collections.singletonList(nextVersionBinding));
+
+        when(nextVersionAlternateExchange.getCategory()).thenReturn(ExchangeController.TYPE);
+        when(nextVersionAlternateExchange.getCategory()).thenReturn(ExchangeController.TYPE);
+        when(nextVersionAlternateExchange.getAttribute(LegacyConfiguredObject.NAME)).thenReturn(alternateExchangeName);
+
+        when(nextVersionVirtualHost.getChildren(ExchangeController.TYPE)).thenReturn(Arrays.asList(nextVersionExchange, nextVersionAlternateExchange));
+        when(nextVersionVirtualHost.getChildren(QueueController.TYPE)).thenReturn(Collections.singletonList(nextVersionExchange));
+
+        final LegacyConfiguredObject convertedExchange = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject convertedAltExchange = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject convertedQueue = mock(LegacyConfiguredObject.class);
+        when(_legacyVersionManagementController.convertFromNextVersion(nextVersionQueue)).thenReturn(
+                convertedQueue);
+        when(_legacyVersionManagementController.convertFromNextVersion(nextVersionAlternateExchange)).thenReturn(
+                convertedAltExchange);
+        when(_legacyVersionManagementController.convertFromNextVersion(nextVersionExchange)).thenReturn(convertedExchange);
+
+        final LegacyConfiguredObject destination = _queueController.convertFromNextVersion(nextVersionQueue);
+
+        assertThat(destination.getAttribute("alternateExchange"), is(equalTo(convertedAltExchange)));
+        assertThat(destination.getAttribute("queueFlowControlSizeBytes"), is(equalTo(10000L)));
+        assertThat(destination.getAttribute("queueFlowResumeSizeBytes"), is(equalTo(7000L)));
+        assertThat(destination.getAttribute("messageGroupSharedGroups"), is(equalTo(true)));
+        assertThat(destination.getAttribute("messageGroupKey"), is(equalTo("test")));
+
+        final Collection<LegacyConfiguredObject> children = destination.getChildren(BindingController.TYPE);
+        assertThat(children.size(), is(equalTo(1)));
+
+        final LegacyConfiguredObject o = children.iterator().next();
+        assertThat(o.getCategory(), is(equalTo(BindingController.TYPE)));
+        assertThat(o.getAttribute(AbstractConfiguredObject.NAME), is(equalTo(bindingKey)));
+        assertThat(o.getAttribute("queue"), is(equalTo(convertedQueue)));
+        assertThat(o.getAttribute("exchange"), is(equalTo(convertedExchange)));
+    }
+
+    @Test
+    public void convertAttributesToNextVersion()
+    {
+        final Map<String, Object> attributes = new HashMap<>();
+        attributes.put("queueFlowResumeSizeBytes", 7000L);
+        attributes.put("queueFlowControlSizeBytes", 10000L);
+        attributes.put("messageGroupSharedGroups", true);
+        attributes.put("messageGroupKey", "groupKey");
+        attributes.put("name", "testQueue");
+
+
+        final ConfiguredObject<?> root = mock(ConfiguredObject.class);
+        final List path = Arrays.asList("my-vhn", "my-vh", "testQueue");
+        final Map<String, Object> converted = _queueController.convertAttributesToNextVersion(root, path, attributes);
+
+        assertThat(converted, is(notNullValue()));
+        assertThat(converted.get("overflowPolicy"), is(equalTo("PRODUCER_FLOW_CONTROL")));
+        assertThat(converted.get("maximumQueueDepthBytes"), is(equalTo(10000L)));
+        assertThat(converted.get("messageGroupType"), is(equalTo("SHARED_GROUPS")));
+        assertThat(converted.get("messageGroupKeyOverride"), is(equalTo("groupKey")));
+        assertThat(converted.get("name"), is(equalTo("testQueue")));
+
+        final Object contextObject = converted.get("context");
+        assertThat(contextObject, is(instanceOf(Map.class)));
+
+        final Map<?,?> context =(Map<?,?>)contextObject;
+        assertThat(context.get("queue.queueFlowResumeLimit"), is(equalTo("70.00")));
+    }
+}
\ No newline at end of file
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/SessionControllerTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/SessionControllerTest.java
new file mode 100644
index 0000000..77b5924
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/SessionControllerTest.java
@@ -0,0 +1,95 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.UUID;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class SessionControllerTest extends UnitTestBase
+{
+    private LegacyManagementController _legacyManagementController;
+    private SessionController _sessionController;
+
+    @Before
+    public void setUp()
+    {
+        _legacyManagementController = mock(LegacyManagementController.class);
+        final ManagementController nextVersionManagementController = mock(ManagementController.class);
+        when(_legacyManagementController.getNextVersionManagementController()).thenReturn(
+                nextVersionManagementController);
+        _sessionController = new SessionController(_legacyManagementController, Collections.emptySet());
+    }
+
+    @Test
+    public void convertNextVersionLegacyConfiguredObject()
+    {
+        final UUID sessionID = UUID.randomUUID();
+        final UUID connectionID = UUID.randomUUID();
+
+        final LegacyConfiguredObject nextVersionSession = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject nextVersionConnection = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject nextVersionVirtualHost = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject nextVersionQueue = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject nextVersionConsumer = mock(LegacyConfiguredObject.class);
+
+        when(nextVersionSession.getCategory()).thenReturn(SessionController.TYPE);
+        when(nextVersionSession.getParent(LegacyCategoryControllerFactory.CATEGORY_CONNECTION)).thenReturn(nextVersionConnection);
+        when(nextVersionSession.getAttribute(LegacyConfiguredObject.ID)).thenReturn(sessionID);
+
+        when(nextVersionConnection.getParent(VirtualHostController.TYPE)).thenReturn(nextVersionVirtualHost);
+        when(nextVersionConnection.getAttribute(LegacyConfiguredObject.ID)).thenReturn(connectionID);
+
+        when(nextVersionVirtualHost.getChildren(QueueController.TYPE)).thenReturn(Collections.singletonList(nextVersionQueue));
+        when(nextVersionQueue.getChildren(ConsumerController.TYPE)).thenReturn(Collections.singletonList(nextVersionConsumer));
+        when(nextVersionConsumer.getAttribute("session")).thenReturn(nextVersionSession);
+
+        final LegacyConfiguredObject convertedConsumer = mock(LegacyConfiguredObject.class);
+        final LegacyConfiguredObject convertedConnection = mock(LegacyConfiguredObject.class);
+        when(_legacyManagementController.convertFromNextVersion(nextVersionConsumer)).thenReturn(convertedConsumer);
+        when(_legacyManagementController.convertFromNextVersion(nextVersionConnection)).thenReturn(convertedConnection);
+
+        final LegacyConfiguredObject convertedSession = _sessionController.convertNextVersionLegacyConfiguredObject(nextVersionSession);
+
+        assertThat(convertedSession.getAttribute(LegacyConfiguredObject.ID), is(equalTo(sessionID)));
+        assertThat(convertedSession.getParent(LegacyCategoryControllerFactory.CATEGORY_CONNECTION), is(equalTo(convertedConnection)));
+
+        final Collection<LegacyConfiguredObject> consumers = convertedSession.getChildren(ConsumerController.TYPE);
+        assertThat(consumers, is(notNullValue()));
+        assertThat(consumers.size(), is(equalTo(1)));
+        assertThat(consumers.iterator().next(), is(equalTo(convertedConsumer)));
+    }
+}
\ No newline at end of file
diff --git a/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/VirtualHostControllerTest.java b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/VirtualHostControllerTest.java
new file mode 100644
index 0000000..8b37137
--- /dev/null
+++ b/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/controller/v6_1/category/VirtualHostControllerTest.java
@@ -0,0 +1,104 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.qpid.server.management.plugin.controller.v6_1.category;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.hamcrest.CoreMatchers.instanceOf;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.CoreMatchers.notNullValue;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import org.apache.qpid.server.management.plugin.ManagementController;
+import org.apache.qpid.server.management.plugin.controller.LegacyConfiguredObject;
+import org.apache.qpid.server.management.plugin.controller.LegacyManagementController;
+import org.apache.qpid.server.model.ConfiguredObject;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+public class VirtualHostControllerTest extends UnitTestBase
+{
+    private VirtualHostController _virtualHostController;
+
+    @Before
+    public void setUp()
+    {
+        final LegacyManagementController legacyManagementController = mock(LegacyManagementController.class);
+        final ManagementController nextVersionManagementController = mock(ManagementController.class);
+        when(legacyManagementController.getNextVersionManagementController()).thenReturn(
+                nextVersionManagementController);
+        when(legacyManagementController.getVersion()).thenReturn("6.1");
+        _virtualHostController = new VirtualHostController(legacyManagementController, Collections.emptySet());
+    }
+
+    @Test
+    public void convertNextVersionLegacyConfiguredObject()
+    {
+        final LegacyConfiguredObject nextVersionVirtualHost = mock(LegacyConfiguredObject.class);
+        when(nextVersionVirtualHost.getAttribute(LegacyConfiguredObject.NAME)).thenReturn("test");
+
+        final LegacyConfiguredObject converted =
+                _virtualHostController.convertNextVersionLegacyConfiguredObject(nextVersionVirtualHost);
+
+        assertThat(converted, is(notNullValue()));
+        assertThat(converted.getCategory(), is(equalTo(VirtualHostController.TYPE)));
+        assertThat(converted.getAttribute(LegacyConfiguredObject.NAME), is(equalTo("test")));
+        assertThat(converted.getAttribute("modelVersion"), is(equalTo("6.1")));
+        assertThat(converted.getAttribute("queue_deadLetterQueueEnabled"), is(equalTo(false)));
+    }
+
+    @Test
+    public void convertAttributesToNextVersion()
+    {
+        Map<String, Object> attributes = new HashMap<>();
+        attributes.put(LegacyConfiguredObject.NAME, "test");
+        attributes.put("queue_deadLetterQueueEnabled", true);
+        Map<String, String> context = new HashMap<>();
+        context.put("queue.deadLetterQueueEnabled", "true");
+        context.put("virtualhost.housekeepingCheckPeriod", "30");
+        attributes.put(LegacyConfiguredObject.CONTEXT, context);
+
+        final ConfiguredObject<?> root = mock(ConfiguredObject.class);
+        final List<String> path = Collections.singletonList("test-vhn");
+        Map<String, Object> converted = _virtualHostController.convertAttributesToNextVersion(root, path, attributes);
+
+        assertThat(converted, is(notNullValue()));
+        assertThat(converted.get(LegacyConfiguredObject.NAME), is(equalTo("test")));
+
+        assertThat(converted.containsKey("queue_deadLetterQueueEnabled"), is(equalTo(false)));
+
+        Object contextObject = converted.get(LegacyConfiguredObject.CONTEXT);
+        assertThat(converted, is(instanceOf(Map.class)));
+
+        Map<?,?> convertedContext = (Map<?,?>)contextObject;
+
+        assertThat(convertedContext.get("virtualhost.housekeepingCheckPeriod"), is(equalTo("30")));
+        assertThat(convertedContext.containsKey("queue.deadLetterQueueEnabled"), is(equalTo(false)));
+    }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org