From 09484dd10bba52e2bc2c7bc2ce742e4a8e58a8be Mon Sep 17 00:00:00 2001
From: Jean-Noël Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Thu, 10 Mar 2016 08:40:41 +0000
Subject: [PATCH] Added MonitorData class to simplify writing monitored objects

---
 opendj-server-legacy/src/main/java/org/opends/server/config/JMXMBean.java                                           |   48 -
 opendj-server-legacy/src/main/java/org/opends/server/api/EntryCache.java                                            |    3 
 opendj-server-legacy/src/main/java/org/opends/server/extensions/DiskSpaceMonitor.java                               |   22 
 opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPStatistics.java                             |   33 
 opendj-server-legacy/src/main/java/org/opends/server/monitors/ParallelWorkQueueMonitor.java                         |   40 -
 opendj-server-legacy/src/main/java/org/opends/server/backends/MonitorBackend.java                                   |   20 
 opendj-server-legacy/src/main/java/org/opends/server/monitors/VersionMonitorProvider.java                           |   39 
 opendj-server-legacy/src/main/java/org/opends/server/extensions/DefaultEntryCache.java                              |   10 
 opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileChangeNumberIndexDB.java |   20 
 opendj-server-legacy/src/main/java/org/opends/server/extensions/FIFOEntryCache.java                                 |   23 
 opendj-server-legacy/src/main/java/org/opends/server/replication/server/DataServerHandler.java                      |   67 +-
 opendj-server-legacy/src/test/java/org/opends/server/monitors/TestMonitorProvider.java                              |   18 
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendMonitor.java                         |   54 -
 opendj-server-legacy/src/main/java/org/opends/server/monitors/BackendMonitor.java                                   |   72 -
 opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPStatistics.java                             |  194 +----
 opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/JEMonitor.java                                    |   58 -
 opendj-server-legacy/src/main/java/org/opends/server/monitors/MemoryUsageMonitorProvider.java                       |   30 
 opendj-server-legacy/src/main/java/org/opends/server/extensions/SoftReferenceEntryCache.java                        |   13 
 opendj-server-legacy/src/main/java/org/opends/server/api/MonitorProvider.java                                       |    9 
 opendj-server-legacy/src/main/java/org/opends/server/api/MonitorData.java                                           |  226 ++++++
 opendj-server-legacy/src/main/java/org/opends/server/monitors/StackTraceMonitorProvider.java                        |   73 +-
 opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationDomain.java                     |   37 
 opendj-server-legacy/src/main/java/org/opends/server/replication/server/MessageHandler.java                         |   18 
 opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationMonitor.java                    |  118 +--
 opendj-server-legacy/src/main/java/org/opends/server/monitors/EntryCacheMonitorProvider.java                        |   17 
 opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileReplicaDB.java           |   23 
 opendj-server-legacy/src/main/java/org/opends/server/monitors/SystemInfoMonitorProvider.java                        |   76 -
 opendj-server-legacy/src/test/java/org/opends/server/replication/StressTest.java                                    |   52 
 opendj-server-legacy/src/main/java/org/opends/server/replication/server/ReplicationServerDomain.java                |   29 
 opendj-server-legacy/src/main/java/org/opends/server/replication/server/LightweightServerHandler.java               |   62 -
 opendj-server-legacy/src/main/java/org/opends/server/backends/pdb/PDBMonitor.java                                   |   68 -
 opendj-server-legacy/src/main/java/org/opends/server/monitors/TraditionalWorkQueueMonitor.java                      |   45 -
 opendj-server-legacy/src/main/java/org/opends/server/replication/server/ReplicationServerHandler.java               |   34 
 opendj-server-legacy/src/main/java/org/opends/server/extensions/EntryCacheCommon.java                               |   69 -
 opendj-server-legacy/src/main/java/org/opends/server/monitors/ClientConnectionMonitorProvider.java                  |   45 
 opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/LDAPReplicationDomain.java                  |   31 
 opendj-server-legacy/src/main/java/org/opends/server/monitors/ConnectionHandlerMonitor.java                         |   63 -
 opendj-server-legacy/src/main/java/org/opends/server/replication/server/ServerHandler.java                          |   77 +-
 38 files changed, 817 insertions(+), 1,119 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/api/EntryCache.java b/opendj-server-legacy/src/main/java/org/opends/server/api/EntryCache.java
index 16cba35..c43023c 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/api/EntryCache.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/api/EntryCache.java
@@ -26,7 +26,6 @@
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.admin.std.server.EntryCacheCfg;
 import org.opends.server.monitors.EntryCacheMonitorProvider;
-import org.opends.server.types.Attribute;
 import org.forgerock.opendj.ldap.DN;
 import org.opends.server.types.Entry;
 import org.opends.server.types.InitializationException;
@@ -348,7 +347,7 @@
    *          be returned to the client if the corresponding monitor
    *          entry is requested.
    */
-  public abstract List<Attribute> getMonitorData();
+  public abstract MonitorData getMonitorData();
 
   /**
    * Retrieves the current number of entries stored within the cache.
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/api/MonitorData.java b/opendj-server-legacy/src/main/java/org/opends/server/api/MonitorData.java
new file mode 100644
index 0000000..8729922
--- /dev/null
+++ b/opendj-server-legacy/src/main/java/org/opends/server/api/MonitorData.java
@@ -0,0 +1,226 @@
+/*
+ * The contents of this file are subject to the terms of the Common Development and
+ * Distribution License (the License). You may not use this file except in compliance with the
+ * License.
+ *
+ * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
+ * specific language governing permission and limitations under the License.
+ *
+ * When distributing Covered Software, include this CDDL Header Notice in each file and include
+ * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
+ * Header, with the fields enclosed by brackets [] replaced by your own identifying
+ * information: "Portions Copyright [year] [name of copyright owner]".
+ *
+ * Copyright 2016 ForgeRock AS.
+ */
+package org.opends.server.api;
+
+import static org.opends.server.core.DirectoryServer.*;
+
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.UUID;
+
+import org.forgerock.opendj.ldap.ByteString;
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.GeneralizedTime;
+import org.forgerock.opendj.ldap.schema.AttributeType;
+import org.forgerock.opendj.ldap.schema.CoreSchema;
+import org.forgerock.opendj.ldap.schema.Syntax;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeBuilder;
+import org.opends.server.types.Attributes;
+import org.opends.server.types.PublicAPI;
+import org.opends.server.types.StabilityLevel;
+
+/**
+ * This class is used to hold monitoring data, i.e. a list of attributes. It provides convenient
+ * methods to easily build such data.
+ * <p>
+ * <strong>Note:</strong> <br>
+ * Creating monitor entries may become a lot easier once we've migrated to the SDK Entry class:
+ *
+ * <pre>
+ * Entry entry = ...;
+ * entry.addAttribute("stringStat", "aString")
+ *       .addAttribute("integerStat", 12345)
+ *       .addAttribute("dnStat", DN.valueOf("dc=aDN");
+ * </pre>
+ *
+ * We could also envisage an annotation based approach where we determine the monitor content from
+ * annotated fields/methods in an object.
+ */
+@PublicAPI(stability = StabilityLevel.PRIVATE)
+public final class MonitorData implements Iterable<Attribute>
+{
+  private final List<Attribute> attrs;
+
+  /** Constructor to use when the number of attributes to create is unknown. */
+  public MonitorData()
+  {
+    attrs = new ArrayList<>();
+  }
+
+  /**
+   * Constructor that accepts the number of attributes to create.
+   *
+   * @param expectedAttributesCount
+   *          number of attributes that will be added
+   */
+  public MonitorData(int expectedAttributesCount)
+  {
+    attrs = new ArrayList<>(expectedAttributesCount);
+  }
+
+  /**
+   * Adds an attribute with the provided name and value.
+   *
+   * @param attrName
+   *          the attribute name
+   * @param attrValue
+   *          the attribute value
+   */
+  public void add(String attrName, Object attrValue)
+  {
+    Syntax syntax;
+    if (attrValue instanceof String
+        || attrValue instanceof ByteString
+        || attrValue instanceof Float
+        || attrValue instanceof Double)
+    {
+      // coming first because they are the most common types
+      syntax = getDefaultStringSyntax();
+    }
+    else if (attrValue instanceof Number)
+    {
+      syntax = getDefaultIntegerSyntax();
+    }
+    else if (attrValue instanceof Boolean)
+    {
+      syntax = getDefaultBooleanSyntax();
+    }
+    else if (attrValue instanceof DN)
+    {
+      syntax = getDefaultDNSyntax();
+    }
+    else if (attrValue instanceof Date)
+    {
+      syntax = CoreSchema.getGeneralizedTimeSyntax();
+      attrValue = GeneralizedTime.valueOf((Date) attrValue);
+    }
+    else if (attrValue instanceof Calendar)
+    {
+      syntax = CoreSchema.getGeneralizedTimeSyntax();
+      attrValue = GeneralizedTime.valueOf((Calendar) attrValue);
+    }
+    else if (attrValue instanceof UUID)
+    {
+      syntax = CoreSchema.getUUIDSyntax();
+    }
+    else
+    {
+      syntax = getDefaultStringSyntax();
+    }
+    add(attrName, syntax, attrValue);
+  }
+
+  private void add(String attrName, Syntax syntax, Object attrValue)
+  {
+    AttributeType attrType = getAttributeType(attrName, syntax);
+    attrs.add(Attributes.create(attrType, String.valueOf(attrValue)));
+  }
+
+  /**
+   * Adds an attribute with the provided name and value if the value is not null.
+   *
+   * @param attrName
+   *          the attribute name
+   * @param attrValue
+   *          the attribute value
+   */
+  public void addIfNotNull(String attrName, Object attrValue)
+  {
+    if (attrValue != null)
+    {
+      add(attrName, attrValue);
+    }
+  }
+
+  /**
+   * Adds an attribute with the provided name and values.
+   *
+   * @param attrName
+   *          the attribute name
+   * @param attrValues
+   *          the attribute values
+   */
+  public void add(String attrName, Collection<?> attrValues)
+  {
+    AttributeBuilder builder = new AttributeBuilder(attrName);
+    builder.addAllStrings(attrValues);
+    attrs.add(builder.toAttribute());
+  }
+
+  /**
+   * Adds all the properties from the provided bean as attributes, prepending the provided prefix.
+   *
+   * @param bean
+   *          the bean from which to read the properties
+   * @param attributesPrefix
+   *          the prefix to prepend to the attributes read from the bean
+   * @throws ReflectiveOperationException
+   *           if a problem occurs while reading the properties of the bean
+   */
+  public void addBean(Object bean, String attributesPrefix) throws ReflectiveOperationException
+  {
+    for (Method method : bean.getClass().getMethods())
+    {
+      if (method.getName().startsWith("get"))
+      {
+        Class<?> returnType = method.getReturnType();
+        if (returnType.equals(int.class) || returnType.equals(long.class) || returnType.equals(String.class))
+        {
+          addStatAttribute(attributesPrefix, bean, method, 3);
+        }
+      }
+      else if (method.getName().startsWith("is") && method.getReturnType().equals(boolean.class))
+      {
+        addStatAttribute(attributesPrefix, bean, method, 2);
+      }
+    }
+  }
+
+  private void addStatAttribute(String attrPrefix, Object stats, Method method, int skipNameLen)
+      throws ReflectiveOperationException
+  {
+    String attrName = attrPrefix + method.getName().substring(skipNameLen);
+    add(attrName, method.invoke(stats));
+  }
+
+  @Override
+  public Iterator<Attribute> iterator()
+  {
+    return attrs.iterator();
+  }
+
+  /**
+   * Returns the number of attributes.
+   *
+   * @return the number of attributes
+   */
+  public int size()
+  {
+    return attrs.size();
+  }
+
+  @Override
+  public String toString()
+  {
+    return getClass().getName() + attrs;
+  }
+}
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/api/MonitorProvider.java b/opendj-server-legacy/src/main/java/org/opends/server/api/MonitorProvider.java
index eab8cb5..f5dc3c5 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/api/MonitorProvider.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/api/MonitorProvider.java
@@ -12,10 +12,12 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2006-2010 Sun Microsystems, Inc.
- * Portions Copyright 2014-2015 ForgeRock AS.
+ * Portions Copyright 2014-2016 ForgeRock AS.
  */
 package org.opends.server.api;
 
+import static org.opends.server.util.ServerConstants.*;
+
 import java.util.List;
 import java.util.concurrent.Executors;
 import java.util.concurrent.ScheduledExecutorService;
@@ -26,13 +28,10 @@
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
-import org.opends.server.types.Attribute;
 import org.opends.server.types.DirectoryConfig;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.ObjectClass;
 
-import static org.opends.server.util.ServerConstants.*;
-
 /**
  * This class defines the set of methods and structures that must be
  * implemented by a Directory Server module that can provide usage,
@@ -197,6 +196,6 @@
    *          be returned to the client if the corresponding monitor
    *          entry is requested.
    */
-  public abstract List<Attribute> getMonitorData();
+  public abstract MonitorData getMonitorData();
 }
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/MonitorBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/MonitorBackend.java
index 561edc3..66a5c70 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/MonitorBackend.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/MonitorBackend.java
@@ -51,6 +51,7 @@
 import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.admin.std.server.MonitorBackendCfg;
 import org.opends.server.api.Backend;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
 import org.opends.server.config.ConfigEntry;
 import org.opends.server.core.AddOperation;
@@ -781,31 +782,34 @@
     final ObjectClass monitorOC = monitorProvider.getMonitorObjectClass();
     final HashMap<ObjectClass, String> monitorClasses = newObjectClasses(monitorOC, monitorOC.getPrimaryName());
 
-    final List<Attribute> monitorAttrs = monitorProvider.getMonitorData();
-    final HashMap<AttributeType, List<Attribute>> attrMap = new LinkedHashMap<>(monitorAttrs.size() + 1);
+    final MonitorData monitorAttrs = monitorProvider.getMonitorData();
+    final Map<AttributeType, List<Attribute>> attrMap = asMap(monitorAttrs);
 
     // Make sure to include the RDN attribute.
     final AVA ava = entryDN.rdn().getFirstAVA();
     final AttributeType rdnType = ava.getAttributeType();
     final ByteString rdnValue = ava.getAttributeValue();
-
     attrMap.put(rdnType, Attributes.createAsList(rdnType, rdnValue));
 
-    // Take the rest of the information from the monitor data.
+    return newEntry(entryDN, monitorClasses, attrMap, new HashMap<AttributeType, List<Attribute>>(0));
+  }
+
+  private Map<AttributeType, List<Attribute>> asMap(MonitorData monitorAttrs)
+  {
+    final Map<AttributeType, List<Attribute>> results = new LinkedHashMap<>(monitorAttrs.size() + 1);
     for (final Attribute a : monitorAttrs)
     {
       final AttributeType type = a.getAttributeDescription().getAttributeType();
 
-      List<Attribute> attrs = attrMap.get(type);
+      List<Attribute> attrs = results.get(type);
       if (attrs == null)
       {
         attrs = new ArrayList<>();
-        attrMap.put(type, attrs);
+        results.put(type, attrs);
       }
       attrs.add(a);
     }
-
-    return newEntry(entryDN, monitorClasses, attrMap, new HashMap<AttributeType, List<Attribute>>(0));
+    return results;
   }
 
   private HashMap<ObjectClass, String> newObjectClasses(ObjectClass objectClass, String objectClassName)
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/JEMonitor.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/JEMonitor.java
index ce6c5f5..d2222ee 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/JEMonitor.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/jeb/JEMonitor.java
@@ -18,19 +18,10 @@
 
 import static org.opends.server.util.StaticUtils.*;
 
-import java.lang.reflect.Method;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
 import org.forgerock.i18n.slf4j.LocalizedLogger;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.forgerock.opendj.ldap.schema.Syntax;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.Attributes;
 
 import com.sleepycat.je.Environment;
 import com.sleepycat.je.JEVersion;
@@ -59,54 +50,25 @@
   }
 
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
     try
     {
-      List<Attribute> monitorAttrs = new ArrayList<>();
+      final StatsConfig statsConfig = new StatsConfig();
 
-      monitorAttrs.add(Attributes.create("JEVersion", JEVersion.CURRENT_VERSION.getVersionString()));
-
-      StatsConfig statsConfig = new StatsConfig();
-      addAttributesForStatsObject(monitorAttrs, "Environment", env.getStats(statsConfig));
-      addAttributesForStatsObject(monitorAttrs, "Transaction", env.getTransactionStats(statsConfig));
-
+      final MonitorData monitorAttrs = new MonitorData();
+      monitorAttrs.add("JEVersion", JEVersion.CURRENT_VERSION.getVersionString());
+      monitorAttrs.addBean(env.getStats(statsConfig), "Environment");
+      monitorAttrs.addBean(env.getTransactionStats(statsConfig), "Transaction");
       return monitorAttrs;
     }
     catch (Exception e)
     {
       logger.traceException(e);
-      return Collections.singletonList(Attributes.create("JEInfo", stackTraceToSingleLineString(e)));
-    }
-  }
 
-  private void addAttributesForStatsObject(List<Attribute> monitorAttrs, String attrPrefix, Object stats)
-  {
-    for (Method method : stats.getClass().getMethods())
-    {
-      final Class<?> returnType = method.getReturnType();
-      if (method.getName().startsWith("get")
-          && (returnType.equals(int.class) || returnType.equals(long.class)))
-      {
-        addStatAttribute(monitorAttrs, attrPrefix, stats, method);
-      }
-    }
-  }
-
-  private void addStatAttribute(List<Attribute> monitorAttrs, String attrPrefix, Object stats, Method method)
-  {
-    final Syntax integerSyntax = DirectoryServer.getDefaultIntegerSyntax();
-    try
-    {
-      // Remove the 'get' from the method name and add the prefix.
-      String attrName = attrPrefix + method.getName().substring(3);
-
-      AttributeType attrType = DirectoryServer.getAttributeType(attrName, integerSyntax);
-      monitorAttrs.add(Attributes.create(attrType, String.valueOf(method.invoke(stats))));
-    }
-    catch (Exception e)
-    {
-      logger.traceException(e);
+      MonitorData monitorAttrs = new MonitorData(1);
+      monitorAttrs.add("JEInfo", stackTraceToSingleLineString(e));
+      return monitorAttrs;
     }
   }
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pdb/PDBMonitor.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pdb/PDBMonitor.java
index a2bf9c8..9bd037b 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pdb/PDBMonitor.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pdb/PDBMonitor.java
@@ -11,27 +11,21 @@
  * Header, with the fields enclosed by brackets [] replaced by your own identifying
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
- * Copyright 2015 ForgeRock AS.
+ * Copyright 2015-2016 ForgeRock AS.
  */
 package org.opends.server.backends.pdb;
 
 import static org.opends.server.util.StaticUtils.*;
 
-import java.lang.reflect.Method;
 import java.rmi.RemoteException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
 
 import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.Attributes;
 
 import com.persistit.Management.BufferPoolInfo;
 import com.persistit.Management.TreeInfo;
 import com.persistit.Management.VolumeInfo;
-import com.persistit.Management.WrappedRemoteException;
 import com.persistit.Persistit;
 
 /** Monitoring class for PDB, populating cn=monitor statistics using reflection on objects methods. */
@@ -53,71 +47,39 @@
   }
 
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
     try
     {
-      List<Attribute> monitorAttrs = new ArrayList<>();
-      monitorAttrs.add(Attributes.create("PDBVersion", db.getManagement().getVersion()));
+      MonitorData monitorAttrs = new MonitorData();
+      monitorAttrs.add("PDBVersion", db.getManagement().getVersion());
 
       for(BufferPoolInfo bufferInfo : db.getManagement().getBufferPoolInfoArray())
       {
-        addAttributesForStatsObject(monitorAttrs, "PDBBuffer", bufferInfo);
+        monitorAttrs.addBean(bufferInfo, "PDBBuffer");
       }
-      addAttributesForStatsObject(monitorAttrs, "PDBJournal", db.getManagement().getJournalInfo());
-      addAttributesForStatsObject(monitorAttrs, "PDBTransaction", db.getManagement().getTransactionInfo());
+      monitorAttrs.addBean(db.getManagement().getJournalInfo(), "PDBJournal");
+      monitorAttrs.addBean(db.getManagement().getTransactionInfo(), "PDBTransaction");
       for (VolumeInfo vol : db.getManagement().getVolumeInfoArray())
       {
-        addAttributesForStatsObject(monitorAttrs, "PDBVolume", vol);
+        monitorAttrs.addBean(vol, "PDBVolume");
         for (TreeInfo tree : db.getManagement().getTreeInfoArray(vol.getName()))
         {
           // For the time being, depth is not reported.
-          monitorAttrs.add(Attributes.create("PDBVolumeTree", vol.getName() + tree.getName()
+          monitorAttrs.add("PDBVolumeTree", vol.getName() + tree.getName()
               + ", traverse=" + tree.getTraverseCounter()
               + ", fetch=" + tree.getFetchCounter()
               + ", store=" + tree.getStoreCounter()
-              + ", remove=" + tree.getRemoveCounter()));
+              + ", remove=" + tree.getRemoveCounter());
         }
       }
       return monitorAttrs;
     }
-    catch (RemoteException e)
+    catch (ReflectiveOperationException | RemoteException e)
     {
-      return Collections.singletonList(Attributes.create("PDBInfo", stackTraceToSingleLineString(e)));
-    }
-  }
-
-  private void addAttributesForStatsObject(List<Attribute> monitorAttrs, String attrPrefix, Object stats)
-    throws RemoteException
-  {
-    for (Method method : stats.getClass().getMethods())
-    {
-      if (method.getName().startsWith("get"))
-      {
-        Class<?> returnType = method.getReturnType();
-        if (returnType.equals(int.class) || returnType.equals(long.class) || returnType.equals(String.class))
-        {
-          addStatAttribute(monitorAttrs, attrPrefix, stats, method, 3);
-        }
-      }
-      else if (method.getName().startsWith("is") && method.getReturnType().equals(boolean.class))
-      {
-        addStatAttribute(monitorAttrs, attrPrefix, stats, method, 2);
-      }
-    }
-  }
-
-  private void addStatAttribute(List<Attribute> monitorAttrs, String attrPrefix, Object stats,
-      Method method, int skipNameLen) throws WrappedRemoteException
-  {
-    try
-    {
-      String attrName = attrPrefix + method.getName().substring(skipNameLen);
-      monitorAttrs.add(Attributes.create(attrName, String.valueOf(method.invoke(stats))));
-    }
-    catch (Exception e)
-    {
-      throw new WrappedRemoteException(e);
+      MonitorData monitorAttrs = new MonitorData(1);
+      monitorAttrs.add("PDBInfo", stackTraceToSingleLineString(e));
+      return monitorAttrs;
     }
   }
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendMonitor.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendMonitor.java
index 86c3a45..87162a8 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendMonitor.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/BackendMonitor.java
@@ -12,11 +12,12 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2006-2010 Sun Microsystems, Inc.
- * Portions Copyright 2014-2015 ForgeRock AS.
+ * Portions Copyright 2014-2016 ForgeRock AS.
  */
 package org.opends.server.backends.pluggable;
 
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -25,10 +26,8 @@
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeBuilder;
-import org.opends.server.types.Attributes;
 import org.opends.server.types.SearchFilter;
 import org.opends.server.util.TimeThread;
 
@@ -100,55 +99,47 @@
     return name;
   }
 
-  /**
-   * Retrieves a set of attributes containing monitor data that should be
-   * returned to the client if the corresponding monitor entry is requested.
-   *
-   * @return A set of attributes containing monitor data that should be
-   *         returned to the client if the corresponding monitor entry is requested.
-   */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
-    List<Attribute> monitorAttrs = new ArrayList<>();
+    MonitorData monitorAttrs = new MonitorData(5);
 
-    AttributeBuilder needReindex = createNeedReindex("need-reindex");
-    if (needReindex.size() > 0)
+    Collection<String> needReindexValues = createNeedReindexValues();
+    if (needReindexValues.size() > 0)
     {
-      monitorAttrs.add(needReindex.toAttribute());
+      monitorAttrs.add("need-reindex", needReindexValues);
     }
 
     if (filterUseEnabled)
     {
-      monitorAttrs.add(createAttribute("filter-use-startTime", startTimeStamp));
-      monitorAttrs.add(createFilterUse("filter-use"));
-      monitorAttrs.add(createAttribute("filter-use-indexed", indexedSearchCount));
-      monitorAttrs.add(createAttribute("filter-use-unindexed", unindexedSearchCount));
+      monitorAttrs.add("filter-use-startTime", startTimeStamp);
+      monitorAttrs.add("filter-use", createFilterUseValues());
+      monitorAttrs.add("filter-use-indexed", indexedSearchCount);
+      monitorAttrs.add("filter-use-unindexed", unindexedSearchCount);
     }
 
     return monitorAttrs;
   }
 
-  private AttributeBuilder createNeedReindex(String attrName)
+  private Collection<String> createNeedReindexValues()
   {
-    AttributeBuilder needReindex = new AttributeBuilder(attrName);
+    Collection<String> values = new ArrayList<>();
     for (EntryContainer ec : rootContainer.getEntryContainers())
     {
       for (Tree tree : ec.listTrees())
       {
         if (tree instanceof Index && !((Index) tree).isTrusted())
         {
-          needReindex.add(tree.getName().toString());
+          values.add(tree.getName().toString());
         }
       }
     }
-    return needReindex;
+    return values;
   }
 
-  private Attribute createFilterUse(String attrName)
+  private List<String> createFilterUseValues()
   {
-    AttributeBuilder builder = new AttributeBuilder(attrName);
-
+    List<String> values = new ArrayList<>();
     StringBuilder value = new StringBuilder();
     synchronized (filterToStats)
     {
@@ -158,16 +149,11 @@
         value.append(" hits:").append(entry.getValue().hits.get());
         value.append(" maxmatches:").append(entry.getValue().maxMatchingEntries);
         value.append(" message:").append(entry.getValue().failureReason);
-        builder.add(value.toString());
+        values.add(value.toString());
         value.setLength(0);
       }
     }
-    return builder.toAttribute();
-  }
-
-  private Attribute createAttribute(String attrName, Object value)
-  {
-    return Attributes.create(attrName, String.valueOf(value));
+    return values;
   }
 
   /**
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/config/JMXMBean.java b/opendj-server-legacy/src/main/java/org/opends/server/config/JMXMBean.java
index e94cbd9..4450df7 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/config/JMXMBean.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/config/JMXMBean.java
@@ -42,6 +42,7 @@
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
 import org.opends.server.api.AlertGenerator;
 import org.opends.server.api.ClientConnection;
@@ -54,7 +55,6 @@
 import org.opends.server.protocols.internal.SearchRequest;
 import org.opends.server.protocols.jmx.Credential;
 import org.opends.server.protocols.jmx.JmxClientConnection;
-import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.opendj.ldap.DN;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.InvokableMethod;
@@ -413,8 +413,7 @@
               stringValues.add(value.toString());
             }
 
-            String[] valueArray = new String[stringValues.size()];
-            stringValues.toArray(valueArray);
+            String[] valueArray = stringValues.toArray(new String[stringValues.size()]);
             return new Attribute(name, valueArray);
           }
           else
@@ -568,47 +567,10 @@
       {
         logger.traceException(e);
       }
-
-      // It's possible that this is a monitor attribute rather than a
-      // configurable one. Check all of those.
-      AttributeType attrType = DirectoryServer.getAttributeType(name);
-
-monitorLoop:
-      for (MonitorProvider<? extends MonitorProviderCfg> monitor :
-           monitorProviders)
+      Attribute attr = getJmxAttribute(name);
+      if (attr != null)
       {
-        for (org.opends.server.types.Attribute a : monitor.getMonitorData())
-        {
-          if (attrType.equals(a.getAttributeDescription().getAttributeType()))
-          {
-            if (a.isEmpty())
-            {
-              continue;
-            }
-
-            Iterator<ByteString> iterator = a.iterator();
-            ByteString value = iterator.next();
-
-            if (iterator.hasNext())
-            {
-              List<String> stringValues = newArrayList(value.toString());
-              while (iterator.hasNext())
-              {
-                value = iterator.next();
-                stringValues.add(value.toString());
-              }
-
-              String[] valueArray = new String[stringValues.size()];
-              stringValues.toArray(valueArray);
-              attrList.add(new Attribute(name, valueArray));
-            }
-            else
-            {
-              attrList.add(new Attribute(name, value.toString()));
-            }
-            break monitorLoop;
-          }
-        }
+        attrList.add(attr);
       }
     }
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/extensions/DefaultEntryCache.java b/opendj-server-legacy/src/main/java/org/opends/server/extensions/DefaultEntryCache.java
index a684b8f..7b47046 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/extensions/DefaultEntryCache.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/extensions/DefaultEntryCache.java
@@ -16,21 +16,20 @@
  */
 package org.opends.server.extensions;
 
-import java.util.Collections;
 import java.util.List;
 import java.util.SortedMap;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.admin.std.server.EntryCacheCfg;
 import org.opends.server.api.Backend;
 import org.opends.server.api.BackendInitializationListener;
 import org.opends.server.api.EntryCache;
+import org.opends.server.api.MonitorData;
 import org.opends.server.core.DirectoryServer;
-import org.opends.server.types.Attribute;
-import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.ldap.DN;
 import org.opends.server.types.Entry;
 import org.opends.server.types.InitializationException;
@@ -276,9 +275,8 @@
     return new ConfigChangeResult();
   }
 
-  /** {@inheritDoc} */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
     // The sum of cache hits of all active entry cache implementations.
     long entryCacheHits = 0;
@@ -304,7 +302,7 @@
         );
     } catch (Exception e) {
       logger.traceException(e);
-      return Collections.emptyList();
+      return new MonitorData(0);
     }
   }
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/extensions/DiskSpaceMonitor.java b/opendj-server-legacy/src/main/java/org/opends/server/extensions/DiskSpaceMonitor.java
index 9b8a0e8..50ccd56 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/extensions/DiskSpaceMonitor.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/extensions/DiskSpaceMonitor.java
@@ -17,7 +17,6 @@
 package org.opends.server.extensions;
 
 import static org.opends.messages.CoreMessages.*;
-import static org.opends.server.core.DirectoryServer.*;
 import static org.opends.server.util.CollectionUtils.*;
 import static org.opends.server.util.ServerConstants.*;
 
@@ -45,6 +44,7 @@
 import org.opends.server.admin.std.server.MonitorProviderCfg;
 import org.opends.server.api.AlertGenerator;
 import org.opends.server.api.DiskSpaceMonitorHandler;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
 import org.opends.server.api.ServerShutdownListener;
 import org.opends.server.core.DirectoryServer;
@@ -96,13 +96,13 @@
         throws ConfigException, InitializationException {
     }
 
-    /** {@inheritDoc} */
     @Override
-    public List<Attribute> getMonitorData() {
-      final List<Attribute> monitorAttrs = new ArrayList<>();
-      monitorAttrs.add(attr("disk-dir", getDefaultStringSyntax(), directory.getPath()));
-      monitorAttrs.add(attr("disk-free", getDefaultIntegerSyntax(), getFreeSpace()));
-      monitorAttrs.add(attr("disk-state", getDefaultStringSyntax(), getState()));
+    public MonitorData getMonitorData()
+    {
+      final MonitorData monitorAttrs = new MonitorData(3);
+      monitorAttrs.add("disk-dir", directory.getPath());
+      monitorAttrs.add("disk-free", getFreeSpace());
+      monitorAttrs.add("disk-state", getState());
       return monitorAttrs;
     }
 
@@ -353,19 +353,17 @@
     // Not used...
   }
 
-  /** {@inheritDoc} */
   @Override
   public String getMonitorInstanceName() {
     return INSTANCENAME;
   }
 
-  /** {@inheritDoc} */
   @Override
-  public List<Attribute> getMonitorData() {
-    return new ArrayList<>();
+  public MonitorData getMonitorData()
+  {
+    return new MonitorData(0);
   }
 
-  /** {@inheritDoc} */
   @Override
   public void run()
   {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/extensions/EntryCacheCommon.java b/opendj-server-legacy/src/main/java/org/opends/server/extensions/EntryCacheCommon.java
index 7ffa102..bb06b58 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/extensions/EntryCacheCommon.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/extensions/EntryCacheCommon.java
@@ -16,11 +16,8 @@
  */
 package org.opends.server.extensions;
 
-
-import org.forgerock.i18n.slf4j.LocalizedLogger;
 import static org.opends.server.util.StaticUtils.*;
 
-import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -28,18 +25,14 @@
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.LocalizableMessageDescriptor;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.Attributes;
 import org.forgerock.opendj.ldap.DN;
 import org.opends.server.types.DirectoryException;
+import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.ldap.ResultCode;
+import org.opends.server.api.MonitorData;
 import org.opends.server.types.SearchFilter;
 
-
-
-/**
- * This class provides some common tools to all entry cache implementations.
- */
+/** This class provides some common tools to all entry cache implementations. */
 public class EntryCacheCommon
 {
 
@@ -53,19 +46,11 @@
    */
   public static enum ConfigPhase
   {
-    /**
-     * Indicates that entry cache is in initialization check phase.
-     */
+    /** Indicates that entry cache is in initialization check phase. */
     PHASE_INIT,
-
-    /**
-     * Indicates that entry cache is in configuration check phase.
-     */
+    /** Indicates that entry cache is in configuration check phase. */
     PHASE_ACCEPTABLE,
-
-    /**
-     * Indicates that entry cache is applying its configuration.
-     */
+    /** Indicates that entry cache is applying its configuration. */
     PHASE_APPLY
   }
 
@@ -360,7 +345,7 @@
    *
    * @return  A set of generic attributes containing monitor data.
    */
-  public static List<Attribute> getGenericMonitorData(
+  public static MonitorData getGenericMonitorData(
     Long cacheHits,
     Long cacheMisses,
     Long cacheSize,
@@ -368,54 +353,30 @@
     Long cacheCount,
     Long maxCacheCount)
   {
-    List<Attribute> attrs = new ArrayList<>();
+    MonitorData attrs = new MonitorData();
 
     if (cacheHits != null)
     {
-      attrs
-          .add(Attributes.create("entryCacheHits", cacheHits.toString()));
+      attrs.add("entryCacheHits", cacheHits);
 
       // Cache misses is required to get cache tries and hit ratio.
       if (cacheMisses != null)
       {
         Long cacheTries = cacheHits + cacheMisses;
-        attrs.add(Attributes.create("entryCacheTries", cacheTries
-            .toString()));
+        attrs.add("entryCacheTries", cacheTries);
 
         Double hitRatioRaw = cacheTries > 0 ? cacheHits.doubleValue()
             / cacheTries.doubleValue() : cacheHits.doubleValue() / 1;
         Double hitRatio = hitRatioRaw * 100D;
-        attrs.add(Attributes.create("entryCacheHitRatio", Long
-            .toString(hitRatio.longValue())));
+        attrs.add("entryCacheHitRatio", hitRatio);
       }
     }
 
-    if (cacheSize != null)
-    {
-      attrs.add(Attributes.create("currentEntryCacheSize", cacheSize
-          .toString()));
-    }
-
-    if (maxCacheSize != null)
-    {
-      attrs.add(Attributes.create("maxEntryCacheSize", maxCacheSize
-          .toString()));
-    }
-
-    if (cacheCount != null)
-    {
-      attrs.add(Attributes.create("currentEntryCacheCount", cacheCount
-          .toString()));
-    }
-
-    if (maxCacheCount != null)
-    {
-      attrs.add(Attributes.create("maxEntryCacheCount", maxCacheCount
-          .toString()));
-    }
+    attrs.addIfNotNull("currentEntryCacheSize", cacheSize);
+    attrs.addIfNotNull("maxEntryCacheSize", maxCacheSize);
+    attrs.addIfNotNull("currentEntryCacheCount", cacheCount);
+    attrs.addIfNotNull("maxEntryCacheCount", maxCacheCount);
 
     return attrs;
   }
-
 }
-
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/extensions/FIFOEntryCache.java b/opendj-server-legacy/src/main/java/org/opends/server/extensions/FIFOEntryCache.java
index 455e108..ad0f407 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/extensions/FIFOEntryCache.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/extensions/FIFOEntryCache.java
@@ -18,7 +18,13 @@
 
 import static org.opends.messages.ExtensionMessages.*;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReadWriteLock;
@@ -26,18 +32,18 @@
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.ldap.DN;
 import org.forgerock.util.Utils;
 import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.admin.std.server.EntryCacheCfg;
 import org.opends.server.admin.std.server.FIFOEntryCacheCfg;
 import org.opends.server.api.Backend;
 import org.opends.server.api.EntryCache;
+import org.opends.server.api.MonitorData;
 import org.opends.server.core.DirectoryServer;
-import org.opends.server.types.Attribute;
 import org.opends.server.types.CacheEntry;
-import org.forgerock.opendj.config.server.ConfigChangeResult;
-import org.forgerock.opendj.ldap.DN;
 import org.opends.server.types.Entry;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.SearchFilter;
@@ -893,25 +899,24 @@
     return errorHandler.getIsAcceptable();
   }
 
-  /** {@inheritDoc} */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
     try {
       return EntryCacheCommon.getGenericMonitorData(
-        Long.valueOf(cacheHits.longValue()),
+        cacheHits.longValue(),
         // If cache misses is maintained by default cache
         // get it from there and if not point to itself.
         DirectoryServer.getEntryCache().getCacheMisses(),
         null,
-        Long.valueOf(maxAllowedMemory),
+        maxAllowedMemory,
         Long.valueOf(dnMap.size()),
         Long.valueOf(
             (maxEntries != Integer.MAX_VALUE && maxEntries != Long.MAX_VALUE) ? maxEntries : 0)
         );
     } catch (Exception e) {
       logger.traceException(e);
-      return Collections.emptyList();
+      return new MonitorData(0);
     }
   }
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/extensions/SoftReferenceEntryCache.java b/opendj-server-legacy/src/main/java/org/opends/server/extensions/SoftReferenceEntryCache.java
index 832c4d4..4f45ef3 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/extensions/SoftReferenceEntryCache.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/extensions/SoftReferenceEntryCache.java
@@ -22,7 +22,6 @@
 import java.lang.ref.ReferenceQueue;
 import java.lang.ref.SoftReference;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -31,6 +30,7 @@
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.forgerock.util.Utils;
 import org.opends.server.admin.server.ConfigurationChangeListener;
@@ -39,10 +39,9 @@
 import org.opends.server.api.Backend;
 import org.opends.server.api.DirectoryThread;
 import org.opends.server.api.EntryCache;
+import org.opends.server.api.MonitorData;
 import org.opends.server.core.DirectoryServer;
-import org.opends.server.types.Attribute;
 import org.opends.server.types.CacheEntry;
-import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.ldap.DN;
 import org.opends.server.types.Entry;
 import org.opends.server.types.InitializationException;
@@ -530,13 +529,12 @@
     }
   }
 
-  /** {@inheritDoc} */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
     try {
       return EntryCacheCommon.getGenericMonitorData(
-        Long.valueOf(cacheHits.longValue()),
+        cacheHits.longValue(),
         // If cache misses is maintained by default cache
         // get it from there and if not point to itself.
         DirectoryServer.getEntryCache().getCacheMisses(),
@@ -547,11 +545,10 @@
         );
     } catch (Exception e) {
       logger.traceException(e);
-      return Collections.emptyList();
+      return new MonitorData(0);
     }
   }
 
-  /** {@inheritDoc} */
   @Override
   public Long getCacheCount()
   {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/monitors/BackendMonitor.java b/opendj-server-legacy/src/main/java/org/opends/server/monitors/BackendMonitor.java
index 1293070..3408eb8 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/monitors/BackendMonitor.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/monitors/BackendMonitor.java
@@ -18,19 +18,18 @@
 
 import static org.opends.server.util.ServerConstants.*;
 
+import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.LinkedList;
-import java.util.List;
+import java.util.Collection;
 
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
 import org.opends.server.api.Backend;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
-import org.opends.server.core.DirectoryServer;
-import org.opends.server.schema.BooleanSyntax;
 import org.forgerock.opendj.ldap.DN;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.opends.server.types.*;
+import org.opends.server.types.DirectoryConfig;
+import org.opends.server.types.ObjectClass;
 
 /**
  * This class implements a monitor provider that will report generic information
@@ -40,19 +39,6 @@
 public class BackendMonitor
        extends MonitorProvider<MonitorProviderCfg>
 {
-  /** The attribute type that will be used to report the backend ID. */
-  private AttributeType backendIDType;
-  /** The attribute type that will be used to report the set of base DNs. */
-  private AttributeType baseDNType;
-  /** The attribute type that will be used to report the number of entries. */
-  private AttributeType entryCountType;
-  /** The attribute type that will be used to report the number of entries per base DN. */
-  private AttributeType baseDNEntryCountType;
-  /** The attribute type that will be used to indicate if a backend is private. */
-  private AttributeType isPrivateType;
-  /** The attribute type that will be used to report the writability mode. */
-  private AttributeType writabilityModeType;
-
   /** The backend with which this monitor is associated. */
   private Backend<?> backend;
 
@@ -76,13 +62,6 @@
   public void initializeMonitorProvider(MonitorProviderCfg configuration)
   {
     monitorName = backend.getBackendID() + " Backend";
-
-    backendIDType = DirectoryServer.getAttributeType(ATTR_MONITOR_BACKEND_ID);
-    baseDNType = DirectoryServer.getAttributeType(ATTR_MONITOR_BACKEND_BASE_DN);
-    entryCountType = DirectoryServer.getAttributeType(ATTR_MONITOR_BACKEND_ENTRY_COUNT);
-    baseDNEntryCountType = DirectoryServer.getAttributeType(ATTR_MONITOR_BASE_DN_ENTRY_COUNT);
-    isPrivateType = DirectoryServer.getAttributeType(ATTR_MONITOR_BACKEND_IS_PRIVATE);
-    writabilityModeType = DirectoryServer.getAttributeType(ATTR_MONITOR_BACKEND_WRITABILITY_MODE);
   }
 
   @Override
@@ -105,26 +84,23 @@
   }
 
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
-    LinkedList<Attribute> attrs = new LinkedList<>();
-
-    attrs.add(Attributes.create(backendIDType, backend.getBackendID()));
-
     DN[] baseDNs = backend.getBaseDNs();
 
-    AttributeBuilder builder = new AttributeBuilder(baseDNType);
-    builder.addAllStrings(Arrays.asList(baseDNs));
-    attrs.add(builder.toAttribute());
+    MonitorData attrs = new MonitorData(6);
+    attrs.add(ATTR_MONITOR_BACKEND_ID, backend.getBackendID());
+    attrs.add(ATTR_MONITOR_BACKEND_BASE_DN, Arrays.asList(baseDNs));
+    attrs.add(ATTR_MONITOR_BACKEND_IS_PRIVATE, backend.isPrivateBackend());
+    attrs.add(ATTR_MONITOR_BACKEND_ENTRY_COUNT, backend.getEntryCount());
+    attrs.add(ATTR_MONITOR_BASE_DN_ENTRY_COUNT, getBackendEntryCounts(baseDNs));
+    attrs.add(ATTR_MONITOR_BACKEND_WRITABILITY_MODE, backend.getWritabilityMode());
+    return attrs;
+  }
 
-    attrs.add(Attributes.create(isPrivateType, BooleanSyntax
-        .createBooleanValue(backend.isPrivateBackend())));
-
-    long backendCount = backend.getEntryCount();
-    attrs.add(Attributes.create(entryCountType, String
-        .valueOf(backendCount)));
-
-    builder = new AttributeBuilder(baseDNEntryCountType);
+  private Collection<String> getBackendEntryCounts(DN[] baseDNs)
+  {
+    Collection<String> results = new ArrayList<>();
     if (baseDNs.length != 1)
     {
       for (DN dn : baseDNs)
@@ -138,7 +114,7 @@
         {
           logger.traceException(ex);
         }
-        builder.add(entryCount + " " + dn);
+        results.add(entryCount + " " + dn);
       }
     }
     else
@@ -146,14 +122,8 @@
       // This is done to avoid recalculating the number of entries
       // using the numSubordinates method in the case where the
       // backend has a single base DN.
-      builder.add(backendCount + " " + baseDNs[0]);
+      results.add(backend.getEntryCount() + " " + baseDNs[0]);
     }
-    attrs.add(builder.toAttribute());
-
-    attrs.add(Attributes.create(writabilityModeType, String
-        .valueOf(backend.getWritabilityMode())));
-
-    return attrs;
+    return results;
   }
 }
-
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/monitors/ClientConnectionMonitorProvider.java b/opendj-server-legacy/src/main/java/org/opends/server/monitors/ClientConnectionMonitorProvider.java
index 08a1506..c826099 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/monitors/ClientConnectionMonitorProvider.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/monitors/ClientConnectionMonitorProvider.java
@@ -12,21 +12,21 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2006-2010 Sun Microsystems, Inc.
- * Portions Copyright 2014-2015 ForgeRock AS.
+ * Portions Copyright 2014-2016 ForgeRock AS.
  */
 package org.opends.server.monitors;
 
-import java.util.List;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.TreeMap;
 
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.admin.std.server.ClientConnectionMonitorProviderCfg;
 import org.opends.server.api.ClientConnection;
 import org.opends.server.api.ConnectionHandler;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
 import org.opends.server.core.DirectoryServer;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeBuilder;
 import org.opends.server.types.InitializationException;
 
 /**
@@ -105,24 +105,20 @@
     }
   }
 
-
-
-  /**
-   * Retrieves a set of attributes containing monitor data that should
-   * be returned to the client if the corresponding monitor entry is
-   * requested.
-   *
-   * @return A set of attributes containing monitor data that should be
-   *         returned to the client if the corresponding monitor entry
-   *         is requested.
-   */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
     // Re-order the connections by connection ID.
     TreeMap<Long, ClientConnection> connMap = new TreeMap<>();
 
-    if (handler == null)
+    if (handler != null)
+    {
+      for (ClientConnection conn : handler.getClientConnections())
+      {
+        connMap.put(conn.getConnectionID(), conn);
+      }
+    }
+    else
     {
       // Get information about all the available connections.
       for (ConnectionHandler<?> hdl : DirectoryServer.getConnectionHandlers())
@@ -134,19 +130,14 @@
         }
       }
     }
-    else
-    {
-      for (ClientConnection conn : handler.getClientConnections())
-      {
-        connMap.put(conn.getConnectionID(), conn);
-      }
-    }
 
-    AttributeBuilder builder = new AttributeBuilder("connection");
+    Collection<String> connectionSummaries = new ArrayList<>(connMap.values().size());
     for (ClientConnection conn : connMap.values())
     {
-      builder.add(conn.getMonitorSummary());
+      connectionSummaries.add(conn.getMonitorSummary());
     }
-    return builder.toAttributeList();
+    MonitorData result = new MonitorData(1);
+    result.add("connection", connectionSummaries);
+    return result;
   }
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/monitors/ConnectionHandlerMonitor.java b/opendj-server-legacy/src/main/java/org/opends/server/monitors/ConnectionHandlerMonitor.java
index dc6dd5b..b482054 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/monitors/ConnectionHandlerMonitor.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/monitors/ConnectionHandlerMonitor.java
@@ -18,17 +18,19 @@
 
 import static org.opends.server.util.ServerConstants.*;
 
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.LinkedList;
-import java.util.List;
 
 import org.opends.server.admin.std.server.ConnectionHandlerCfg;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
 import org.opends.server.api.ClientConnection;
 import org.opends.server.api.ConnectionHandler;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
-import org.opends.server.core.DirectoryServer;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.opends.server.types.*;
+import org.opends.server.types.DirectoryConfig;
+import org.opends.server.types.HostPort;
+import org.opends.server.types.ObjectClass;
 
 /**
  * This class implements a monitor provider that will report generic information
@@ -38,24 +40,6 @@
 public class ConnectionHandlerMonitor
        extends MonitorProvider<MonitorProviderCfg>
 {
-  /** The attribute type that will be used to report the established connections. */
-  private AttributeType connectionsType;
-
-  /** The attribute type that will be used to report the listeners. */
-  private AttributeType listenerType;
-
-  /**
-   * The attribute type that will be used to report the number of established
-   * client connections.
-   */
-  private AttributeType numConnectionsType;
-
-  /** The attribute type that will be used to report the protocol. */
-  private AttributeType protocolType;
-
-  /** The attribute type that will be used to report the config dn . */
-  private AttributeType configDnType;
-
   /** The connection handler with which this monitor is associated. */
   private ConnectionHandler<?> connectionHandler;
 
@@ -80,17 +64,10 @@
 
 
 
-  /** {@inheritDoc} */
   @Override
   public void initializeMonitorProvider(MonitorProviderCfg configuration)
   {
     monitorName = connectionHandler.getConnectionHandlerName();
-
-    connectionsType = DirectoryServer.getAttributeType(ATTR_MONITOR_CONNHANDLER_CONNECTION);
-    listenerType = DirectoryServer.getAttributeType(ATTR_MONITOR_CONNHANDLER_LISTENER);
-    numConnectionsType = DirectoryServer.getAttributeType(ATTR_MONITOR_CONNHANDLER_NUMCONNECTIONS);
-    protocolType = DirectoryServer.getAttributeType(ATTR_MONITOR_CONNHANDLER_PROTOCOL);
-    configDnType = DirectoryServer.getAttributeType(ATTR_MONITOR_CONFIG_DN);
   }
 
 
@@ -119,42 +96,32 @@
 
 
 
-  /** {@inheritDoc} */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
-    LinkedList<Attribute> attrs = new LinkedList<>();
-
-    // Configuration DN
-    attrs.add(Attributes.create(configDnType, connectionHandler.getComponentEntryDN().toString()));
-
-    int numConnections = 0;
     LinkedList<ClientConnection> conns = new LinkedList<>(connectionHandler.getClientConnections());
     LinkedList<HostPort> listeners = new LinkedList<>(connectionHandler.getListeners());
 
-    attrs.add(Attributes.create(protocolType, connectionHandler.getProtocol()));
+    final MonitorData attrs = new MonitorData(5);
+    attrs.add(ATTR_MONITOR_CONFIG_DN, connectionHandler.getComponentEntryDN());
+    attrs.add(ATTR_MONITOR_CONNHANDLER_PROTOCOL, connectionHandler.getProtocol());
 
     if (!listeners.isEmpty())
     {
-      AttributeBuilder builder = new AttributeBuilder(listenerType);
-      builder.addAllStrings(listeners);
-      attrs.add(builder.toAttribute());
+      attrs.add(ATTR_MONITOR_CONNHANDLER_LISTENER, listeners);
     }
 
+    attrs.add(ATTR_MONITOR_CONNHANDLER_NUMCONNECTIONS, conns.size());
     if (!conns.isEmpty())
     {
-      AttributeBuilder builder = new AttributeBuilder(connectionsType);
+      Collection<String> connectionSummaries = new ArrayList<>();
       for (ClientConnection c : conns)
       {
-        numConnections++;
-        builder.add(c.getMonitorSummary());
+        connectionSummaries.add(c.getMonitorSummary());
       }
-      attrs.add(builder.toAttribute());
+      attrs.add(ATTR_MONITOR_CONNHANDLER_CONNECTION, connectionSummaries);
     }
 
-    attrs.add(Attributes.create(numConnectionsType, String
-        .valueOf(numConnections)));
-
     return attrs;
   }
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/monitors/EntryCacheMonitorProvider.java b/opendj-server-legacy/src/main/java/org/opends/server/monitors/EntryCacheMonitorProvider.java
index 7804f44..61e00f4 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/monitors/EntryCacheMonitorProvider.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/monitors/EntryCacheMonitorProvider.java
@@ -12,25 +12,22 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2008-2010 Sun Microsystems, Inc.
- * Portions Copyright 2014-2015 ForgeRock AS.
+ * Portions Copyright 2014-2016 ForgeRock AS.
  */
 package org.opends.server.monitors;
 
-import java.util.Collections;
-import java.util.List;
+import static org.opends.messages.ConfigMessages.*;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
+import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.admin.std.server.EntryCacheCfg;
 import org.opends.server.admin.std.server.EntryCacheMonitorProviderCfg;
 import org.opends.server.api.EntryCache;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
 import org.opends.server.config.ConfigConstants;
-import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.core.DirectoryServer;
-import org.opends.server.types.Attribute;
-
-import static org.opends.messages.ConfigMessages.*;
 
 /**
  * This class defines a Directory Server monitor provider that can be used to
@@ -106,16 +103,14 @@
     }
   }
 
-  /** {@inheritDoc} */
   @Override
   public String getMonitorInstanceName()
   {
     return monitorName;
   }
 
-  /** {@inheritDoc} */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
     if (entryCache != null &&
         monitorConfiguration != null &&
@@ -123,6 +118,6 @@
       // Get monitor data from the cache.
       return entryCache.getMonitorData();
     }
-    return Collections.emptyList();
+    return new MonitorData(0);
   }
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/monitors/MemoryUsageMonitorProvider.java b/opendj-server-legacy/src/main/java/org/opends/server/monitors/MemoryUsageMonitorProvider.java
index 34124d9..5ac492b 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/monitors/MemoryUsageMonitorProvider.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/monitors/MemoryUsageMonitorProvider.java
@@ -12,7 +12,7 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2008-2010 Sun Microsystems, Inc.
- * Portions Copyright 2014-2015 ForgeRock AS.
+ * Portions Copyright 2014-2016 ForgeRock AS.
  */
 package org.opends.server.monitors;
 
@@ -22,16 +22,13 @@
 import java.lang.management.ManagementFactory;
 import java.lang.management.MemoryPoolMXBean;
 import java.lang.management.MemoryUsage;
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.concurrent.TimeUnit;
 
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.admin.std.server.MemoryUsageMonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.Attributes;
 import org.opends.server.types.InitializationException;
 
 /**
@@ -104,9 +101,9 @@
 
 
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
-    ArrayList<Attribute> attrs = new ArrayList<>();
+    MonitorData attrs = new MonitorData();
 
     for (GarbageCollectorMXBean gc :
          ManagementFactory.getGarbageCollectorMXBeans())
@@ -134,10 +131,10 @@
         gcSafeNames.put(gcName, safeName);
       }
 
-      attrs.add(createAttribute(safeName + "-total-collection-count", gcCount));
-      attrs.add(createAttribute(safeName + "-total-collection-duration", gcTime));
-      attrs.add(createAttribute(safeName + "-average-collection-duration", avgGCDuration));
-      attrs.add(createAttribute(safeName + "-recent-collection-duration", recentGCDuration));
+      attrs.add(safeName + "-total-collection-count", gcCount);
+      attrs.add(safeName + "-total-collection-duration", gcTime);
+      attrs.add(safeName + "-average-collection-duration", avgGCDuration);
+      attrs.add(safeName + "-recent-collection-duration", recentGCDuration);
     }
 
     for (MemoryPoolMXBean mp : ManagementFactory.getMemoryPoolMXBeans())
@@ -154,22 +151,15 @@
       }
 
       long currentBytesUsed = currentUsage != null ? currentUsage.getUsed() : 0;
-      attrs.add(createAttribute(safeName + "-current-bytes-used", currentBytesUsed));
+      attrs.add(safeName + "-current-bytes-used", currentBytesUsed);
 
       long collectionBytesUsed = collectionUsage != null ? collectionUsage.getUsed() : 0;
-      attrs.add(createAttribute(safeName + "-bytes-used-after-last-collection", collectionBytesUsed));
+      attrs.add(safeName + "-bytes-used-after-last-collection", collectionBytesUsed);
     }
 
     return attrs;
   }
 
-  private Attribute createAttribute(String name, Object value)
-  {
-    return Attributes.create(name, String.valueOf(value));
-  }
-
-
-
   /**
    * Creates a "safe" version of the provided name, which is acceptable for
    * use as part of an attribute name.
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/monitors/ParallelWorkQueueMonitor.java b/opendj-server-legacy/src/main/java/org/opends/server/monitors/ParallelWorkQueueMonitor.java
index 1f14dc3..6fafe52 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/monitors/ParallelWorkQueueMonitor.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/monitors/ParallelWorkQueueMonitor.java
@@ -16,18 +16,13 @@
  */
 package org.opends.server.monitors;
 
-import static org.opends.server.core.DirectoryServer.*;
-
-import java.util.ArrayList;
 import java.util.concurrent.TimeUnit;
 
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
 import org.opends.server.extensions.ParallelWorkQueue;
-import org.opends.server.types.Attribute;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.opends.server.types.Attributes;
 import org.opends.server.types.InitializationException;
 
 /**
@@ -105,8 +100,6 @@
     return "Work Queue";
   }
 
-
-  /** {@inheritDoc} */
   @Override
   public void run()
   {
@@ -120,18 +113,8 @@
     }
   }
 
-
-
-  /**
-   * Retrieves a set of attributes containing monitor data that should be
-   * returned to the client if the corresponding monitor entry is requested.
-   *
-   * @return  A set of attributes containing monitor data that should be
-   *          returned to the client if the corresponding monitor entry is
-   *          requested.
-   */
   @Override
-  public ArrayList<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
     int backlog = workQueue.size();
     totalBacklog += backlog;
@@ -142,21 +125,12 @@
     }
 
     long averageBacklog = (long) (1.0 * totalBacklog / numPolls);
-    long opsSubmitted = workQueue.getOpsSubmitted();
 
-    ArrayList<Attribute> monitorAttrs = new ArrayList<>();
-    putAttribute(monitorAttrs, ATTR_CURRENT_BACKLOG, backlog);
-    putAttribute(monitorAttrs, ATTR_AVERAGE_BACKLOG, averageBacklog);
-    putAttribute(monitorAttrs, ATTR_MAX_BACKLOG, maxBacklog);
-    // The total number of operations submitted.
-    putAttribute(monitorAttrs, ATTR_OPS_SUBMITTED, opsSubmitted);
-
+    final MonitorData monitorAttrs = new MonitorData(4);
+    monitorAttrs.add(ATTR_CURRENT_BACKLOG, backlog);
+    monitorAttrs.add(ATTR_AVERAGE_BACKLOG, averageBacklog);
+    monitorAttrs.add(ATTR_MAX_BACKLOG, maxBacklog);
+    monitorAttrs.add(ATTR_OPS_SUBMITTED, workQueue.getOpsSubmitted());
     return monitorAttrs;
   }
-
-  private void putAttribute(ArrayList<Attribute> monitorAttrs, String attrName, Object value)
-  {
-    AttributeType attrType = getAttributeType(attrName, getDefaultIntegerSyntax());
-    monitorAttrs.add(Attributes.create(attrType, String.valueOf(value)));
-  }
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/monitors/StackTraceMonitorProvider.java b/opendj-server-legacy/src/main/java/org/opends/server/monitors/StackTraceMonitorProvider.java
index 27c2569..910f6f8 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/monitors/StackTraceMonitorProvider.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/monitors/StackTraceMonitorProvider.java
@@ -12,21 +12,19 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2006-2010 Sun Microsystems, Inc.
- * Portions Copyright 2014-2015 ForgeRock AS.
+ * Portions Copyright 2014-2016 ForgeRock AS.
  */
 package org.opends.server.monitors;
 
-import static org.opends.server.util.CollectionUtils.*;
-
-import java.util.List;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Map;
 import java.util.TreeMap;
 
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.admin.std.server.StackTraceMonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeBuilder;
 import org.opends.server.types.InitializationException;
 
 /**
@@ -52,7 +50,7 @@
   }
 
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
     Map<Thread,StackTraceElement[]> threadStacks = Thread.getAllStackTraces();
 
@@ -63,48 +61,51 @@
       orderedStacks.put(e.getKey().getId(), e);
     }
 
-    AttributeBuilder builder = new AttributeBuilder("jvmThread");
+    Collection<String> jvmThreads = new ArrayList<>();
     for (Map.Entry<Thread,StackTraceElement[]> e : orderedStacks.values())
     {
       Thread t                          = e.getKey();
       StackTraceElement[] stackElements = e.getValue();
 
-      long id = t.getId();
-      builder.add("id=" + id + " ---------- " + t.getName() + " ----------");
+      long tid = t.getId();
+      jvmThreads.add("id=" + tid + " ---------- " + t.getName() + " ----------");
 
       // Create an attribute for the stack trace.
       if (stackElements != null)
       {
-        for (int j=0; j < stackElements.length; j++)
+        for (int j = 0; j < stackElements.length; j++)
         {
-          StringBuilder buffer = new StringBuilder();
-          buffer.append("id=");
-          buffer.append(id);
-          buffer.append(" frame[");
-          buffer.append(j);
-          buffer.append("]=");
-
-          buffer.append(stackElements[j].getClassName());
-          buffer.append(".");
-          buffer.append(stackElements[j].getMethodName());
-          buffer.append("(");
-          buffer.append(stackElements[j].getFileName());
-          buffer.append(":");
-          if (stackElements[j].isNativeMethod())
-          {
-            buffer.append("native");
-          }
-          else
-          {
-            buffer.append(stackElements[j].getLineNumber());
-          }
-          buffer.append(")");
-
-          builder.add(buffer.toString());
+          jvmThreads.add(toString(tid, j, stackElements[j]));
         }
       }
     }
 
-    return newArrayList(builder.toAttribute());
+    MonitorData result = new MonitorData(1);
+    result.add("jvmThread", jvmThreads);
+    return result;
+  }
+
+  private String toString(long tid, int frame, StackTraceElement stackElement)
+  {
+    StringBuilder buffer = new StringBuilder();
+    buffer.append("id=").append(tid);
+    buffer.append(" frame[").append(frame).append("]=");
+
+    buffer.append(stackElement.getClassName());
+    buffer.append(".");
+    buffer.append(stackElement.getMethodName());
+    buffer.append("(");
+    buffer.append(stackElement.getFileName());
+    buffer.append(":");
+    if (stackElement.isNativeMethod())
+    {
+      buffer.append("native");
+    }
+    else
+    {
+      buffer.append(stackElement.getLineNumber());
+    }
+    buffer.append(")");
+    return buffer.toString();
   }
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/monitors/SystemInfoMonitorProvider.java b/opendj-server-legacy/src/main/java/org/opends/server/monitors/SystemInfoMonitorProvider.java
index 517e0ad..adb99d3 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/monitors/SystemInfoMonitorProvider.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/monitors/SystemInfoMonitorProvider.java
@@ -12,7 +12,7 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2006-2010 Sun Microsystems, Inc.
- * Portions Copyright 2012-2015 ForgeRock AS.
+ * Portions Copyright 2012-2016 ForgeRock AS.
  */
 package org.opends.server.monitors;
 
@@ -21,9 +21,7 @@
 import java.lang.management.ManagementFactory;
 import java.lang.management.RuntimeMXBean;
 import java.net.InetAddress;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 
@@ -33,11 +31,9 @@
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.admin.std.server.SystemInfoMonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
 import org.opends.server.core.DirectoryServer;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeBuilder;
-import org.opends.server.types.Attributes;
 import org.opends.server.types.InitializationException;
 
 /**
@@ -65,22 +61,22 @@
   }
 
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
-    ArrayList<Attribute> attrs = new ArrayList<>(13);
+    MonitorData attrs = new MonitorData(13);
 
-    attrs.add(createAttribute("javaVersion", System.getProperty("java.version")));
-    attrs.add(createAttribute("javaVendor", System.getProperty("java.vendor")));
-    attrs.add(createAttribute("jvmVersion", System.getProperty("java.vm.version")));
-    attrs.add(createAttribute("jvmVendor", System.getProperty("java.vm.vendor")));
-    attrs.add(createAttribute("javaHome", System.getProperty("java.home")));
-    attrs.add(createAttribute("classPath", System.getProperty("java.class.path")));
-    attrs.add(createAttribute("workingDirectory", System.getProperty("user.dir")));
+    attrs.add("javaVersion", System.getProperty("java.version"));
+    attrs.add("javaVendor", System.getProperty("java.vendor"));
+    attrs.add("jvmVersion", System.getProperty("java.vm.version"));
+    attrs.add("jvmVendor", System.getProperty("java.vm.vendor"));
+    attrs.add("javaHome", System.getProperty("java.home"));
+    attrs.add("classPath", System.getProperty("java.class.path"));
+    attrs.add("workingDirectory", System.getProperty("user.dir"));
 
     String osInfo = System.getProperty("os.name") + " " +
                     System.getProperty("os.version") + " " +
                     System.getProperty("os.arch");
-    attrs.add(createAttribute("operatingSystem", osInfo));
+    attrs.add("operatingSystem", osInfo);
     String sunOsArchDataModel = System.getProperty("sun.arch.data.model");
     if (sunOsArchDataModel != null)
     {
@@ -89,17 +85,16 @@
       {
         jvmArch += "-bit";
       }
-      attrs.add(createAttribute("jvmArchitecture", jvmArch));
+      attrs.add("jvmArchitecture", jvmArch);
     }
     else
     {
-      attrs.add(createAttribute("jvmArchitecture","unknown"));
+      attrs.add("jvmArchitecture", "unknown");
     }
 
     try
     {
-      attrs.add(createAttribute("systemName",
-                     InetAddress.getLocalHost().getCanonicalHostName()));
+      attrs.add("systemName", InetAddress.getLocalHost().getCanonicalHostName());
     }
     catch (Exception e)
     {
@@ -108,19 +103,19 @@
 
 
     Runtime runtime = Runtime.getRuntime();
-    attrs.add(createAttribute("availableCPUs", runtime.availableProcessors()));
-    attrs.add(createAttribute("maxMemory", runtime.maxMemory()));
-    attrs.add(createAttribute("usedMemory", runtime.totalMemory()));
-    attrs.add(createAttribute("freeUsedMemory", runtime.freeMemory()));
+    attrs.add("availableCPUs", runtime.availableProcessors());
+    attrs.add("maxMemory", runtime.maxMemory());
+    attrs.add("usedMemory", runtime.totalMemory());
+    attrs.add("freeUsedMemory", runtime.freeMemory());
     String installPath = DirectoryServer.getServerRoot();
     if (installPath != null)
     {
-      attrs.add(createAttribute("installPath", installPath));
+      attrs.add("installPath", installPath);
     }
     String instancePath = DirectoryServer.getInstanceRoot();
     if (instancePath != null)
     {
-      attrs.add(createAttribute("instancePath", instancePath));
+      attrs.add("instancePath", instancePath);
     }
 
     // Get the JVM input arguments.
@@ -141,42 +136,23 @@
         argList.append("\"");
       }
 
-      attrs.add(createAttribute("jvmArguments", argList.toString()));
+      attrs.add("jvmArguments", argList);
     }
 
-    // Get the list of supported SSL protocols and ciphers.
-    Collection<String> supportedTlsProtocols;
-    Collection<String> supportedTlsCiphers;
     try
     {
       final SSLContext context = SSLContext.getDefault();
       final SSLParameters parameters = context.getSupportedSSLParameters();
-      supportedTlsProtocols = Arrays.asList(parameters.getProtocols());
-      supportedTlsCiphers = Arrays.asList(parameters.getCipherSuites());
+      attrs.add(ATTR_SUPPORTED_TLS_PROTOCOLS, Arrays.asList(parameters.getProtocols()));
+      attrs.add(ATTR_SUPPORTED_TLS_CIPHERS, Arrays.asList(parameters.getCipherSuites()));
     }
     catch (Exception e)
     {
       // A default SSL context should always be available.
-      supportedTlsProtocols = Collections.emptyList();
-      supportedTlsCiphers = Collections.emptyList();
+      attrs.add(ATTR_SUPPORTED_TLS_PROTOCOLS, Collections.emptyList());
+      attrs.add(ATTR_SUPPORTED_TLS_CIPHERS, Collections.emptyList());
     }
 
-    addAttribute(attrs, ATTR_SUPPORTED_TLS_PROTOCOLS, supportedTlsProtocols);
-    addAttribute(attrs, ATTR_SUPPORTED_TLS_CIPHERS, supportedTlsCiphers);
-
     return attrs;
   }
-
-  private void addAttribute(ArrayList<Attribute> attrs, String attrName, Collection<String> values)
-  {
-    AttributeBuilder builder = new AttributeBuilder(attrName);
-    builder.addAllStrings(values);
-    attrs.add(builder.toAttribute());
-  }
-
-  private Attribute createAttribute(String name, Object value)
-  {
-    return Attributes.create(name, String.valueOf(value));
-  }
 }
-
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/monitors/TraditionalWorkQueueMonitor.java b/opendj-server-legacy/src/main/java/org/opends/server/monitors/TraditionalWorkQueueMonitor.java
index c09a439..c2413b3 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/monitors/TraditionalWorkQueueMonitor.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/monitors/TraditionalWorkQueueMonitor.java
@@ -16,18 +16,13 @@
  */
 package org.opends.server.monitors;
 
-import static org.opends.server.core.DirectoryServer.*;
-
-import java.util.ArrayList;
 import java.util.concurrent.TimeUnit;
 
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
 import org.opends.server.extensions.TraditionalWorkQueue;
-import org.opends.server.types.Attribute;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.opends.server.types.Attributes;
 import org.opends.server.types.InitializationException;
 
 /**
@@ -109,8 +104,6 @@
     return "Work Queue";
   }
 
-
-  /** {@inheritDoc} */
   @Override
   public void run()
   {
@@ -124,18 +117,8 @@
     }
   }
 
-
-
-  /**
-   * Retrieves a set of attributes containing monitor data that should be
-   * returned to the client if the corresponding monitor entry is requested.
-   *
-   * @return  A set of attributes containing monitor data that should be
-   *          returned to the client if the corresponding monitor entry is
-   *          requested.
-   */
   @Override
-  public ArrayList<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
     int backlog = workQueue.size();
     totalBacklog += backlog;
@@ -144,26 +127,14 @@
     {
       maxBacklog = backlog;
     }
-
     long averageBacklog = (long) (1.0 * totalBacklog / numPolls);
 
-    long opsSubmitted = workQueue.getOpsSubmitted();
-    long rejectedQueueFull = workQueue.getOpsRejectedDueToQueueFull();
-
-    ArrayList<Attribute> monitorAttrs = new ArrayList<>();
-    putAttribute(monitorAttrs, ATTR_CURRENT_BACKLOG, backlog);
-    putAttribute(monitorAttrs, ATTR_AVERAGE_BACKLOG, averageBacklog);
-    putAttribute(monitorAttrs, ATTR_MAX_BACKLOG, maxBacklog);
-    // The total number of operations submitted.
-    putAttribute(monitorAttrs, ATTR_OPS_SUBMITTED, opsSubmitted);
-    // The total number of operations rejected due to a full work queue.
-    putAttribute(monitorAttrs, ATTR_OPS_REJECTED_QUEUE_FULL, rejectedQueueFull);
+    final MonitorData monitorAttrs = new MonitorData(5);
+    monitorAttrs.add(ATTR_CURRENT_BACKLOG, backlog);
+    monitorAttrs.add(ATTR_AVERAGE_BACKLOG, averageBacklog);
+    monitorAttrs.add(ATTR_MAX_BACKLOG, maxBacklog);
+    monitorAttrs.add(ATTR_OPS_SUBMITTED, workQueue.getOpsSubmitted());
+    monitorAttrs.add(ATTR_OPS_REJECTED_QUEUE_FULL, workQueue.getOpsRejectedDueToQueueFull());
     return monitorAttrs;
   }
-
-  private void putAttribute(ArrayList<Attribute> monitorAttrs, String attrName, Object value)
-  {
-    AttributeType attrType = getAttributeType(attrName, getDefaultIntegerSyntax());
-    monitorAttrs.add(Attributes.create(attrType, String.valueOf(value)));
-  }
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/monitors/VersionMonitorProvider.java b/opendj-server-legacy/src/main/java/org/opends/server/monitors/VersionMonitorProvider.java
index cc2ba06..cb46f19 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/monitors/VersionMonitorProvider.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/monitors/VersionMonitorProvider.java
@@ -16,14 +16,10 @@
  */
 package org.opends.server.monitors;
 
-import java.util.ArrayList;
-import java.util.List;
-
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.admin.std.server.VersionMonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.Attributes;
 import org.opends.server.types.InitializationException;
 import org.opends.server.util.DynamicConstants;
 
@@ -70,44 +66,39 @@
   }
 
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
-    ArrayList<Attribute> attrs = new ArrayList<>(12);
+    MonitorData attrs = new MonitorData(12);
 
-    attrs.add(createAttribute(ATTR_PRODUCT_NAME, DynamicConstants.PRODUCT_NAME));
-    attrs.add(createAttribute(ATTR_SHORT_NAME, DynamicConstants.SHORT_NAME));
-    attrs.add(createAttribute(ATTR_MAJOR_VERSION, DynamicConstants.MAJOR_VERSION));
-    attrs.add(createAttribute(ATTR_MINOR_VERSION, DynamicConstants.MINOR_VERSION));
-    attrs.add(createAttribute(ATTR_POINT_VERSION, DynamicConstants.POINT_VERSION));
+    attrs.add(ATTR_PRODUCT_NAME, DynamicConstants.PRODUCT_NAME);
+    attrs.add(ATTR_SHORT_NAME, DynamicConstants.SHORT_NAME);
+    attrs.add(ATTR_MAJOR_VERSION, DynamicConstants.MAJOR_VERSION);
+    attrs.add(ATTR_MINOR_VERSION, DynamicConstants.MINOR_VERSION);
+    attrs.add(ATTR_POINT_VERSION, DynamicConstants.POINT_VERSION);
 
     String versionQualifier = DynamicConstants.VERSION_QUALIFIER;
     if (versionQualifier != null && versionQualifier.length() > 0)
     {
-      attrs.add(createAttribute(ATTR_VERSION_QUALIFIER, versionQualifier));
+      attrs.add(ATTR_VERSION_QUALIFIER, versionQualifier);
     }
 
     int buildNumber = DynamicConstants.BUILD_NUMBER;
     if (buildNumber > 0)
     {
-      attrs.add(createAttribute(ATTR_BUILD_NUMBER, buildNumber));
+      attrs.add(ATTR_BUILD_NUMBER, buildNumber);
     }
 
     String fixIDs = DynamicConstants.FIX_IDS;
     if (fixIDs != null && fixIDs.length() > 0)
     {
-      attrs.add(createAttribute(ATTR_FIX_IDS, fixIDs));
+      attrs.add(ATTR_FIX_IDS, fixIDs);
     }
 
-    attrs.add(createAttribute(ATTR_REVISION, DynamicConstants.REVISION));
-    attrs.add(createAttribute(ATTR_BUILD_ID, DynamicConstants.BUILD_ID));
-    attrs.add(createAttribute(ATTR_COMPACT_VERSION, DynamicConstants.COMPACT_VERSION_STRING));
-    attrs.add(createAttribute(ATTR_FULL_VERSION, DynamicConstants.FULL_VERSION_STRING));
+    attrs.add(ATTR_REVISION, DynamicConstants.REVISION);
+    attrs.add(ATTR_BUILD_ID, DynamicConstants.BUILD_ID);
+    attrs.add(ATTR_COMPACT_VERSION, DynamicConstants.COMPACT_VERSION_STRING);
+    attrs.add(ATTR_FULL_VERSION, DynamicConstants.FULL_VERSION_STRING);
 
     return attrs;
   }
-
-  private Attribute createAttribute(String name, Object value)
-  {
-    return Attributes.create(name, String.valueOf(value));
-  }
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPStatistics.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPStatistics.java
index 0a57026..3e84e41 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPStatistics.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/http/HTTPStatistics.java
@@ -11,7 +11,7 @@
  * Header, with the fields enclosed by brackets [] replaced by your own identifying
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
- * Copyright 2013-2015 ForgeRock AS.
+ * Copyright 2013-2016 ForgeRock AS.
  */
 package org.opends.server.protocols.http;
 
@@ -23,8 +23,8 @@
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 
+import org.opends.server.api.MonitorData;
 import org.opends.server.protocols.ldap.LDAPStatistics;
-import org.opends.server.types.Attribute;
 
 /**
  * Collects statistics for HTTP. This class inherits from {@link LDAPStatistics}
@@ -93,39 +93,24 @@
     super.clearStatistics();
   }
 
-  /** {@inheritDoc} */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
-    // first take a snapshot of all the data as fast as possible
-    final int totalCount = this.requestsTotalCount.get();
-    final Map<String, Integer> totalCountsSnapshot = new HashMap<>();
-    for (Entry<String, AtomicInteger> entry : requestMethodsTotalCount.entrySet())
-    {
-      totalCountsSnapshot.put(entry.getKey(), entry.getValue().get());
-    }
-    final Map<String, Long> totalTimesSnapshot = new HashMap<>();
-    for (Entry<String, AtomicLong> entry1 : requestMethodsTotalTime.entrySet())
-    {
-      totalTimesSnapshot.put(entry1.getKey(), entry1.getValue().get());
-    }
-
-    // do the same with the underlying data
-    final List<Attribute> results = super.getMonitorData();
-    addAll(results, totalCountsSnapshot, "ds-mon-http-", "-requests-total-count");
-    addAll(results, totalTimesSnapshot, "ds-mon-resident-time-http-", "-requests-total-time");
-    results.add(createAttribute("ds-mon-http-requests-total-count", Integer.toString(totalCount)));
+    final MonitorData results = super.getMonitorData();
+    addAll(results, requestMethodsTotalCount, "ds-mon-http-", "-requests-total-count");
+    addAll(results, requestMethodsTotalTime, "ds-mon-resident-time-http-", "-requests-total-time");
+    results.add("ds-mon-http-requests-total-count", requestsTotalCount.get());
     return results;
   }
 
-  private void addAll(final List<Attribute> results,
+  private void addAll(final MonitorData results,
       final Map<String, ?> toOutput, String prefix, String suffix)
   {
     for (Entry<String, ?> entry : toOutput.entrySet())
     {
       final String httpMethod = entry.getKey();
       final String nb = entry.getValue().toString();
-      results.add(createAttribute(prefix + httpMethod + suffix, nb));
+      results.add(prefix + httpMethod + suffix, nb);
     }
   }
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPStatistics.java b/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPStatistics.java
index 5cdfb67..1325fa0 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPStatistics.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/protocols/ldap/LDAPStatistics.java
@@ -20,16 +20,13 @@
 import static org.opends.server.protocols.ldap.LDAPConstants.*;
 import static org.opends.server.util.ServerConstants.*;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.Attributes;
 import org.opends.server.types.DirectoryConfig;
 import org.opends.server.types.ObjectClass;
 import org.opends.server.types.OperationType;
@@ -170,150 +167,86 @@
       return DirectoryConfig.getObjectClass(OC_MONITOR_CONNHANDLERSTATS, true);
   }
 
-
-  /**
-   * Retrieves a set of attributes containing monitor data that should
-   * be returned to the client if the corresponding monitor entry is
-   * requested.
-   *
-   * @return A set of attributes containing monitor data that should be
-   *         returned to the client if the corresponding monitor entry
-   *         is requested.
-   */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
-      List<Attribute> attrs = new ArrayList<>();
-
-      long tmpAbandonRequests = abandonRequests.get();
-      long tmpAddRequests = addRequests.get();
-      long tmpAddResponses = addResponses.get();
-      long tmpBindRequests = bindRequests.get();
-      long tmpBindResponses = bindResponses.get();
-      long tmpBytesRead = bytesRead.get();
-      long tmpBytesWritten = bytesWritten.get();
-      long tmpCompareRequests = compareRequests.get();
-      long tmpCompareResponses = compareResponses.get();
-      long tmpConnectionsClosed = connectionsClosed.get();
-      long tmpConnectionsEstablished = connectionsEstablished.get();
-      long tmpDeleteRequests = deleteRequests.get();
-      long tmpDeleteResponses = deleteResponses.get();
-      long tmpExtendedRequests = extendedRequests.get();
-      long tmpExtendedResponses = extendedResponses.get();
-      long tmpMessagesRead = messagesRead.get();
-      long tmpMessagesWritten = messagesWritten.get();
-      long tmpModifyRequests = modifyRequests.get();
-      long tmpModifyResponses = modifyResponses.get();
-      long tmpModifyDNRequests = modifyDNRequests.get();
-      long tmpModifyDNResponses = modifyDNResponses.get();
-      long tmpOperationsAbandoned = operationsAbandoned.get();
-      long tmpOperationsCompleted = operationsCompleted.get();
-      long tmpOperationsInitiated = operationsInitiated.get();
-      long tmpSearchRequests = searchRequests.get();
-      long tmpSearchOneRequests = searchOneRequests.get();
-      long tmpSearchSubRequests = searchSubRequests.get();
-      long tmpSearchEntries = searchResultEntries.get();
-      long tmpSearchReferences = searchResultReferences.get();
-      long tmpSearchResultsDone = searchResultsDone.get();
-      long tmpUnbindRequests = unbindRequests.get();
-      long tmpAddOperationCount = addOperationCount.get();
-      long tmpAddOperationTime = addOperationTime.get();
-      long tmpSearchOperationCount = searchOperationCount.get();
-      long tmpSearchOperationTime = searchOperationTime.get();
-      long tmpDelOperationCount = delOperationCount.get();
-      long tmpDelOperationTime = delOperationTime.get();
-      long tmpBindOperationCount = bindOperationCount.get();
-      long tmpBindOperationTime = bindOperationTime.get();
-      long tmpUnbindOperationCount = unbindOperationCount.get();
-      long tmpUnbindOperationTime = unbindOperationTime.get();
-      long tmpCompOperationCount = compOperationCount.get();
-      long tmpCompOperationTime = compOperationTime.get();
-      long tmpModOperationCount = modOperationCount.get();
-      long tmpModOperationTime = modOperationTime.get();
-      long tmpModdnOperationCount = moddnOperationCount.get();
-      long tmpModdnOperationTime = moddnOperationTime.get();
-      long tmpAbandonOperationCount = abandonOperationCount.get();
-      long tmpAbandonOperationTime = abandonOperationTime.get();
-      long tmpExtOperationCount = extOperationCount.get();
-      long tmpExtOperationTime = extOperationTime.get();
-
-
     // Construct the list of attributes to return.
     /* TODO : the attribute names should be constant (in ServerConstants.java
      *        and associated with their objectclass
      *        OC_MONITOR_CONNHANDLERSTATS
      */
-    attrs.add(createAttribute("connectionsEstablished", tmpConnectionsEstablished));
-    attrs.add(createAttribute("connectionsClosed", tmpConnectionsClosed));
-    attrs.add(createAttribute("bytesRead", tmpBytesRead));
-    attrs.add(createAttribute("bytesWritten", tmpBytesWritten));
-    attrs.add(createAttribute("ldapMessagesRead", tmpMessagesRead));
-    attrs.add(createAttribute("ldapMessagesWritten", tmpMessagesWritten));
-    attrs.add(createAttribute("operationsAbandoned", tmpOperationsAbandoned));
-    attrs.add(createAttribute("operationsInitiated", tmpOperationsInitiated));
-    attrs.add(createAttribute("operationsCompleted", tmpOperationsCompleted));
-    attrs.add(createAttribute("abandonRequests", tmpAbandonRequests));
-    attrs.add(createAttribute("addRequests", tmpAddRequests));
-    attrs.add(createAttribute("addResponses", tmpAddResponses));
-    attrs.add(createAttribute("bindRequests", tmpBindRequests));
-    attrs.add(createAttribute("bindResponses", tmpBindResponses));
-    attrs.add(createAttribute("compareRequests", tmpCompareRequests));
-    attrs.add(createAttribute("compareResponses", tmpCompareResponses));
-    attrs.add(createAttribute("deleteRequests", tmpDeleteRequests));
-    attrs.add(createAttribute("deleteResponses", tmpDeleteResponses));
-    attrs.add(createAttribute("extendedRequests", tmpExtendedRequests));
-    attrs.add(createAttribute("extendedResponses", tmpExtendedResponses));
-    attrs.add(createAttribute("modifyRequests", tmpModifyRequests));
-    attrs.add(createAttribute("modifyResponses", tmpModifyResponses));
-    attrs.add(createAttribute("modifyDNRequests", tmpModifyDNRequests));
-    attrs.add(createAttribute("modifyDNResponses", tmpModifyDNResponses));
-    attrs.add(createAttribute("searchRequests", tmpSearchRequests));
-    attrs.add(createAttribute("searchOneRequests", tmpSearchOneRequests));
-    attrs.add(createAttribute("searchSubRequests", tmpSearchSubRequests));
-    attrs.add(createAttribute("searchResultEntries", tmpSearchEntries));
-    attrs.add(createAttribute("searchResultReferences", tmpSearchReferences));
-    attrs.add(createAttribute("searchResultsDone", tmpSearchResultsDone));
-    attrs.add(createAttribute("unbindRequests", tmpUnbindRequests));
+    final MonitorData attrs = new MonitorData(31 + 10 * 2);
+    attrs.add("connectionsEstablished", connectionsEstablished);
+    attrs.add("connectionsClosed", connectionsClosed);
+    attrs.add("bytesRead", bytesRead);
+    attrs.add("bytesWritten", bytesWritten);
+    attrs.add("ldapMessagesRead", messagesRead);
+    attrs.add("ldapMessagesWritten", messagesWritten);
+    attrs.add("operationsAbandoned", operationsAbandoned);
+    attrs.add("operationsInitiated", operationsInitiated);
+    attrs.add("operationsCompleted", operationsCompleted);
+    attrs.add("abandonRequests", abandonRequests);
+    attrs.add("addRequests", addRequests);
+    attrs.add("addResponses", addResponses);
+    attrs.add("bindRequests", bindRequests);
+    attrs.add("bindResponses", bindResponses);
+    attrs.add("compareRequests", compareRequests);
+    attrs.add("compareResponses", compareResponses);
+    attrs.add("deleteRequests", deleteRequests);
+    attrs.add("deleteResponses", deleteResponses);
+    attrs.add("extendedRequests", extendedRequests);
+    attrs.add("extendedResponses", extendedResponses);
+    attrs.add("modifyRequests", modifyRequests);
+    attrs.add("modifyResponses", modifyResponses);
+    attrs.add("modifyDNRequests", modifyDNRequests);
+    attrs.add("modifyDNResponses", modifyDNResponses);
+    attrs.add("searchRequests", searchRequests);
+    attrs.add("searchOneRequests", searchOneRequests);
+    attrs.add("searchSubRequests", searchSubRequests);
+    attrs.add("searchResultEntries", searchResultEntries);
+    attrs.add("searchResultReferences", searchResultReferences);
+    attrs.add("searchResultsDone", searchResultsDone);
+    attrs.add("unbindRequests", unbindRequests);
 
     // adds
-    attrs.add(createAttribute("ds-mon-add-operations-total-count", tmpAddOperationCount));
-    attrs.add(createAttribute("ds-mon-resident-time-add-operations-total-time", tmpAddOperationTime));
+    attrs.add("ds-mon-add-operations-total-count", addOperationCount);
+    attrs.add("ds-mon-resident-time-add-operations-total-time", addOperationTime);
 
     // search
-    attrs.add(createAttribute("ds-mon-search-operations-total-count", tmpSearchOperationCount));
-    attrs.add(createAttribute("ds-mon-resident-time-search-operations-total-time", tmpSearchOperationTime));
+    attrs.add("ds-mon-search-operations-total-count", searchOperationCount);
+    attrs.add("ds-mon-resident-time-search-operations-total-time", searchOperationTime);
 
     // bind
-    attrs.add(createAttribute("ds-mon-bind-operations-total-count", tmpBindOperationCount));
-    attrs.add(createAttribute("ds-mon-resident-time-bind-operations-total-time", tmpBindOperationTime));
+    attrs.add("ds-mon-bind-operations-total-count", bindOperationCount);
+    attrs.add("ds-mon-resident-time-bind-operations-total-time", bindOperationTime);
 
     // unbind
-    attrs.add(createAttribute("ds-mon-unbind-operations-total-count", tmpUnbindOperationCount));
-    attrs.add(createAttribute("ds-mon-resident-time-unbind-operations-total-time", tmpUnbindOperationTime));
+    attrs.add("ds-mon-unbind-operations-total-count", unbindOperationCount);
+    attrs.add("ds-mon-resident-time-unbind-operations-total-time", unbindOperationTime);
 
     // compare
-    attrs.add(createAttribute("ds-mon-compare-operations-total-count", tmpCompOperationCount));
-    attrs.add(createAttribute("ds-mon-resident-time-compare-operations-total-time", tmpCompOperationTime));
+    attrs.add("ds-mon-compare-operations-total-count", compOperationCount);
+    attrs.add("ds-mon-resident-time-compare-operations-total-time", compOperationTime);
 
     // del
-    attrs.add(createAttribute("ds-mon-delete-operations-total-count", tmpDelOperationCount));
-    attrs.add(createAttribute("ds-mon-resident-time-delete-operations-total-time", tmpDelOperationTime));
+    attrs.add("ds-mon-delete-operations-total-count", delOperationCount);
+    attrs.add("ds-mon-resident-time-delete-operations-total-time", delOperationTime);
 
     // mod
-    attrs.add(createAttribute("ds-mon-mod-operations-total-count", tmpModOperationCount));
-    attrs.add(createAttribute("ds-mon-resident-time-mod-operations-total-time", tmpModOperationTime));
+    attrs.add("ds-mon-mod-operations-total-count", modOperationCount);
+    attrs.add("ds-mon-resident-time-mod-operations-total-time", modOperationTime);
 
     // moddn
-    attrs.add(createAttribute("ds-mon-moddn-operations-total-count", tmpModdnOperationCount));
-    attrs.add(createAttribute("ds-mon-resident-time-moddn-operations-total-time", tmpModdnOperationTime));
+    attrs.add("ds-mon-moddn-operations-total-count", moddnOperationCount);
+    attrs.add("ds-mon-resident-time-moddn-operations-total-time", moddnOperationTime);
 
     // abandon
-    attrs.add(createAttribute("ds-mon-abandon-operations-total-count", tmpAbandonOperationCount));
-    attrs.add(createAttribute("ds-mon-resident-time-abandon-operations-total-time", tmpAbandonOperationTime));
+    attrs.add("ds-mon-abandon-operations-total-count", abandonOperationCount);
+    attrs.add("ds-mon-resident-time-abandon-operations-total-time", abandonOperationTime);
 
     // extended
-    attrs.add(createAttribute("ds-mon-extended-operations-total-count", tmpExtOperationCount));
-    attrs.add(createAttribute("ds-mon-resident-time-extended-operations-total-time", tmpExtOperationTime));
+    attrs.add("ds-mon-extended-operations-total-count", extOperationCount);
+    attrs.add("ds-mon-resident-time-extended-operations-total-time", extOperationTime);
 
     return attrs;
   }
@@ -568,25 +501,6 @@
       operationsAbandoned.getAndIncrement();
   }
 
-
-
-  /**
-   * Constructs an attribute using the provided information. It will
-   * use the server's schema definitions.
-   *
-   * @param name
-   *          The name to use for the attribute.
-   * @param value
-   *          The value to use for the attribute.
-   * @return the constructed attribute.
-   */
-  protected Attribute createAttribute(String name, Object value)
-  {
-    return Attributes.create(name, String.valueOf(value));
-  }
-
-
-
   /**
    * Retrieves the number of client connections that have been
    * established.
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/LDAPReplicationDomain.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/LDAPReplicationDomain.java
index 8b7e26a..46795c3 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/LDAPReplicationDomain.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/plugin/LDAPReplicationDomain.java
@@ -23,7 +23,6 @@
 import static org.opends.server.protocols.internal.Requests.*;
 import static org.opends.server.replication.plugin.EntryHistorical.*;
 import static org.opends.server.replication.protocol.OperationContext.*;
-import static org.opends.server.replication.service.ReplicationMonitor.*;
 import static org.opends.server.util.CollectionUtils.*;
 import static org.opends.server.util.ServerConstants.*;
 import static org.opends.server.util.StaticUtils.*;
@@ -80,6 +79,7 @@
 import org.opends.server.api.Backend.BackendOperation;
 import org.opends.server.api.BackendInitializationListener;
 import org.opends.server.api.DirectoryThread;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.ServerShutdownListener;
 import org.opends.server.api.SynchronizationProvider;
 import org.opends.server.backends.task.Task;
@@ -4282,28 +4282,17 @@
     return true;
   }
 
-  /**
-   * Monitoring information for the LDAPReplicationDomain.
-   *
-   * @return Monitoring attributes specific to the LDAPReplicationDomain.
-   */
   @Override
-  public Collection<Attribute> getAdditionalMonitoring()
+  public void addAdditionalMonitoring(MonitorData attributes)
   {
-    List<Attribute> attributes = new ArrayList<>();
-
-    // number of updates in the pending list
-    addMonitorData(attributes, "pending-updates", pendingChanges.size());
-
-    addMonitorData(attributes, "replayed-updates-ok", numReplayedPostOpCalled.get());
-    addMonitorData(attributes, "resolved-modify-conflicts", numResolvedModifyConflicts.get());
-    addMonitorData(attributes, "resolved-naming-conflicts", numResolvedNamingConflicts.get());
-    addMonitorData(attributes, "unresolved-naming-conflicts", numUnresolvedNamingConflicts.get());
-    addMonitorData(attributes, "remote-pending-changes-size", remotePendingChanges.getQueueSize());
-    addMonitorData(attributes, "dependent-changes-size", remotePendingChanges.getDependentChangesSize());
-    addMonitorData(attributes, "changes-in-progress-size", remotePendingChanges.changesInProgressSize());
-
-    return attributes;
+    attributes.add("pending-updates", pendingChanges.size());
+    attributes.add("replayed-updates-ok", numReplayedPostOpCalled);
+    attributes.add("resolved-modify-conflicts", numResolvedModifyConflicts);
+    attributes.add("resolved-naming-conflicts", numResolvedNamingConflicts);
+    attributes.add("unresolved-naming-conflicts", numUnresolvedNamingConflicts);
+    attributes.add("remote-pending-changes-size", remotePendingChanges.getQueueSize());
+    attributes.add("dependent-changes-size", remotePendingChanges.getDependentChangesSize());
+    attributes.add("changes-in-progress-size", remotePendingChanges.changesInProgressSize());
   }
 
   /**
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/DataServerHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/DataServerHandler.java
index a3d1035..b6429e9 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/DataServerHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/DataServerHandler.java
@@ -12,7 +12,7 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2006-2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2015 ForgeRock AS.
+ * Portions Copyright 2011-2016 ForgeRock AS.
  */
 package org.opends.server.replication.server;
 
@@ -22,14 +22,33 @@
 import static org.opends.server.replication.protocol.ProtocolVersion.*;
 
 import java.io.IOException;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.ldap.ResultCode;
-import org.opends.server.replication.common.*;
-import org.opends.server.replication.protocol.*;
-import org.opends.server.types.*;
+import org.opends.server.api.MonitorData;
+import org.opends.server.replication.common.AssuredMode;
+import org.opends.server.replication.common.DSInfo;
+import org.opends.server.replication.common.ServerState;
+import org.opends.server.replication.common.ServerStatus;
+import org.opends.server.replication.common.StatusMachine;
+import org.opends.server.replication.common.StatusMachineEvent;
+import org.opends.server.replication.protocol.ChangeStatusMsg;
+import org.opends.server.replication.protocol.ProtocolVersion;
+import org.opends.server.replication.protocol.ReplServerStartDSMsg;
+import org.opends.server.replication.protocol.ReplicationMsg;
+import org.opends.server.replication.protocol.ServerStartMsg;
+import org.opends.server.replication.protocol.Session;
+import org.opends.server.replication.protocol.StartMsg;
+import org.opends.server.replication.protocol.StartSessionMsg;
+import org.opends.server.replication.protocol.StopMsg;
+import org.opends.server.replication.protocol.TopologyMsg;
+import org.opends.server.types.DirectoryException;
 
 /**
  * This class defines a server handler, which handles all interaction with a
@@ -213,54 +232,38 @@
     return newStatus;
   }
 
-  /** {@inheritDoc} */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
-    // Get the generic ones
-    List<Attribute> attributes = super.getMonitorData();
+    MonitorData attributes = super.getMonitorData();
 
     // Add the specific DS ones
-    attributes.add(Attributes.create("replica", serverURL));
-    attributes.add(Attributes.create("connected-to",
-        this.replicationServer.getMonitorInstanceName()));
+    attributes.add("replica", serverURL);
+    attributes.add("connected-to", replicationServer.getMonitorInstanceName());
 
-    ReplicationDomainMonitorData md =
-        replicationServerDomain.getDomainMonitorData();
+    ReplicationDomainMonitorData md = replicationServerDomain.getDomainMonitorData();
 
     // Oldest missing update
     long approxFirstMissingDate = md.getApproxFirstMissingDate(serverId);
     if (approxFirstMissingDate > 0)
     {
-      Date date = new Date(approxFirstMissingDate);
-      attributes.add(Attributes.create(
-          "approx-older-change-not-synchronized", date.toString()));
-      attributes.add(Attributes.create(
-          "approx-older-change-not-synchronized-millis", String
-          .valueOf(approxFirstMissingDate)));
+      attributes.add("approx-older-change-not-synchronized", new Date(approxFirstMissingDate));
+      attributes.add("approx-older-change-not-synchronized-millis", approxFirstMissingDate);
     }
 
-    // Missing changes
-    attributes.add(Attributes.create("missing-changes",
-        String.valueOf(md.getMissingChanges(serverId))));
-
+    attributes.add("missing-changes", md.getMissingChanges(serverId));
     // Replication delay
-    attributes.add(Attributes.create("approximate-delay",
-        String.valueOf(md.getApproxDelay(serverId))));
+    attributes.add("approximate-delay", md.getApproxDelay(serverId));
 
-    /* get the Server State */
     ServerState state = md.getLDAPServerState(serverId);
     if (state != null)
     {
-      AttributeBuilder builder = new AttributeBuilder("server-state");
-      builder.addAllStrings(state.toStringSet());
-      attributes.add(builder.toAttribute());
+      attributes.add("server-state", state.toStringSet());
     }
 
     return attributes;
   }
 
-  /** {@inheritDoc} */
   @Override
   public String getMonitorInstanceName()
   {
@@ -278,7 +281,6 @@
     return status;
   }
 
-  /** {@inheritDoc} */
   @Override
   public boolean isDataServer()
   {
@@ -510,7 +512,6 @@
         refUrls, eclIncludes, eclIncludesForDeletes, getProtocolVersion());
   }
 
-  /** {@inheritDoc} */
   @Override
   public String toString()
   {
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/LightweightServerHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/LightweightServerHandler.java
index ca6707f..a956b92 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/LightweightServerHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/LightweightServerHandler.java
@@ -12,24 +12,21 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2008-2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2015 ForgeRock AS.
+ * Portions Copyright 2011-2016 ForgeRock AS.
  */
 package org.opends.server.replication.server;
 
-import java.util.ArrayList;
 import java.util.Date;
-import java.util.List;
+import java.util.Set;
 
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigException;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.replication.common.DSInfo;
 import org.opends.server.replication.common.ServerState;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeBuilder;
-import org.opends.server.types.Attributes;
 import org.opends.server.types.InitializationException;
 
 /**
@@ -149,26 +146,16 @@
         + ",cn=" + replServerHandler.getMonitorInstanceName();
   }
 
-  /**
-   * Retrieves a set of attributes containing monitor data that should be
-   * returned to the client if the corresponding monitor entry is requested.
-   *
-   * @return  A set of attributes containing monitor data that should be
-   *          returned to the client if the corresponding monitor entry is
-   *          requested.
-   */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
-    List<Attribute> attributes = new ArrayList<>();
+    MonitorData attributes = new MonitorData(8);
 
     final int serverId = dsInfo.getDsId();
     final ReplicationServerDomain domain = replServerHandler.getDomain();
-    attributes.add(Attributes.create("server-id", String.valueOf(serverId)));
-    attributes.add(Attributes.create("domain-name",
-        domain.getBaseDN().toString()));
-    attributes.add(Attributes.create("connected-to",
-        replServerHandler.getMonitorInstanceName()));
+    attributes.add("server-id", serverId);
+    attributes.add("domain-name", domain.getBaseDN());
+    attributes.add("connected-to", replServerHandler.getMonitorInstanceName());
 
     // Retrieves the topology counters
     final ReplicationDomainMonitorData md = domain.getDomainMonitorData();
@@ -178,36 +165,25 @@
       remoteState = new ServerState();
     }
 
-    // get the Server State
-    AttributeBuilder builder = new AttributeBuilder("server-state");
-    builder.addAllStrings(remoteState.toStringSet());
-    if (builder.size() == 0)
+    Set<String> serverState = remoteState.toStringSet();
+    if (serverState.isEmpty())
     {
-      builder.add("unknown");
+      attributes.add("server-state", "unknown");
     }
-    attributes.add(builder.toAttribute());
+    else
+    {
+      attributes.add("server-state", serverState);
+    }
 
     // Oldest missing update
     long approxFirstMissingDate = md.getApproxFirstMissingDate(serverId);
     if (approxFirstMissingDate > 0)
     {
-      Date date = new Date(approxFirstMissingDate);
-      attributes.add(Attributes.create(
-          "approx-older-change-not-synchronized", date.toString()));
-      attributes.add(Attributes.create(
-          "approx-older-change-not-synchronized-millis", String
-          .valueOf(approxFirstMissingDate)));
+      attributes.add("approx-older-change-not-synchronized", new Date(approxFirstMissingDate));
+      attributes.add("approx-older-change-not-synchronized-millis", approxFirstMissingDate);
     }
-
-    // Missing changes
-    long missingChanges = md.getMissingChanges(serverId);
-    attributes.add(Attributes.create("missing-changes",
-        String.valueOf(missingChanges)));
-
-    // Replication delay
-    long delay = md.getApproxDelay(serverId);
-    attributes.add(Attributes.create("approximate-delay",
-        String.valueOf(delay)));
+    attributes.add("missing-changes", md.getMissingChanges(serverId));
+    attributes.add("approximate-delay", md.getApproxDelay(serverId));
 
     return attributes;
   }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/MessageHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/MessageHandler.java
index e5de9fe..04004d1 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/MessageHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/MessageHandler.java
@@ -17,10 +17,7 @@
 package org.opends.server.replication.server;
 
 import static org.opends.messages.ReplicationMessages.*;
-import static org.opends.server.types.Attributes.*;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.forgerock.i18n.LocalizableMessage;
@@ -28,6 +25,7 @@
 import org.forgerock.opendj.config.server.ConfigException;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.replication.common.CSN;
@@ -35,7 +33,6 @@
 import org.opends.server.replication.protocol.UpdateMsg;
 import org.opends.server.replication.server.changelog.api.ChangelogException;
 import org.opends.server.replication.server.changelog.api.DBCursor;
-import org.opends.server.types.Attribute;
 import org.forgerock.opendj.ldap.DN;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.InitializationException;
@@ -198,15 +195,14 @@
     return inCount;
   }
 
-  /** {@inheritDoc} */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
-    List<Attribute> attributes = new ArrayList<>();
-    attributes.add(create("handler", getMonitorInstanceName()));
-    attributes.add(create("queue-size", String.valueOf(msgQueue.count())));
-    attributes.add(create("queue-size-bytes", String.valueOf(msgQueue.bytesCount())));
-    attributes.add(create("following", String.valueOf(following)));
+    MonitorData attributes = new MonitorData(4);
+    attributes.add("handler", getMonitorInstanceName());
+    attributes.add("queue-size", msgQueue.count());
+    attributes.add("queue-size-bytes", msgQueue.bytesCount());
+    attributes.add("following", following);
     return attributes;
   }
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ReplicationServerDomain.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ReplicationServerDomain.java
index 124f897..652d106 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ReplicationServerDomain.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ReplicationServerDomain.java
@@ -38,6 +38,7 @@
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.replication.common.CSN;
@@ -61,8 +62,6 @@
 import org.opends.server.replication.server.changelog.api.DBCursor;
 import org.opends.server.replication.server.changelog.api.DBCursor.CursorOptions;
 import org.opends.server.replication.server.changelog.api.ReplicationDomainDB;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.Attributes;
 import org.forgerock.opendj.ldap.DN;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.HostPort;
@@ -2273,27 +2272,17 @@
         + ",cn=Replication";
   }
 
-  /** {@inheritDoc} */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
-    // publish the server id and the port number.
-    List<Attribute> attributes = new ArrayList<>();
-    attributes.add(Attributes.create("replication-server-id",
-        String.valueOf(localReplicationServer.getServerId())));
-    attributes.add(Attributes.create("replication-server-port",
-        String.valueOf(localReplicationServer.getReplicationPort())));
-    attributes.add(Attributes.create("domain-name",
-        baseDN.toString()));
-    attributes.add(Attributes.create("generation-id",
-        baseDN + " " + generationId));
+    int serverId = localReplicationServer.getServerId();
 
-    // Missing changes
-    long missingChanges = getDomainMonitorData().getMissingChangesRS(
-        localReplicationServer.getServerId());
-    attributes.add(Attributes.create("missing-changes",
-        String.valueOf(missingChanges)));
-
+    final MonitorData attributes = new MonitorData(5);
+    attributes.add("replication-server-id", serverId);
+    attributes.add("replication-server-port", localReplicationServer.getReplicationPort());
+    attributes.add("domain-name", baseDN);
+    attributes.add("generation-id", baseDN + " " + generationId);
+    attributes.add("missing-changes", getDomainMonitorData().getMissingChangesRS(serverId));
     return attributes;
   }
 
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ReplicationServerHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ReplicationServerHandler.java
index 5fd9cda..a91f18f 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ReplicationServerHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ReplicationServerHandler.java
@@ -29,12 +29,19 @@
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.ldap.DN;
 import org.forgerock.opendj.ldap.ResultCode;
+import org.opends.server.api.MonitorData;
 import org.opends.server.replication.common.DSInfo;
 import org.opends.server.replication.common.RSInfo;
 import org.opends.server.replication.common.ServerState;
 import org.opends.server.replication.common.ServerStatus;
-import org.opends.server.replication.protocol.*;
-import org.opends.server.types.*;
+import org.opends.server.replication.protocol.ProtocolVersion;
+import org.opends.server.replication.protocol.ReplServerStartMsg;
+import org.opends.server.replication.protocol.ReplicationMsg;
+import org.opends.server.replication.protocol.Session;
+import org.opends.server.replication.protocol.StopMsg;
+import org.opends.server.replication.protocol.TopologyMsg;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.HostPort;
 
 /**
  * This class defines a server handler, which handles all interaction with a
@@ -643,30 +650,19 @@
         + ",cn=" + replicationServerDomain.getMonitorInstanceName();
   }
 
-  /** {@inheritDoc} */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
-    // Get the generic ones
-    List<Attribute> attributes = super.getMonitorData();
+    MonitorData attributes = super.getMonitorData();
 
-    // Add the specific RS ones
-    attributes.add(Attributes.create("Replication-Server", serverURL));
+    ReplicationDomainMonitorData md = replicationServerDomain.getDomainMonitorData();
+    attributes.add("Replication-Server", serverURL);
+    attributes.add("missing-changes", md.getMissingChangesRS(serverId));
 
-    ReplicationDomainMonitorData md =
-        replicationServerDomain.getDomainMonitorData();
-
-    // Missing changes
-    attributes.add(Attributes.create("missing-changes",
-        String.valueOf(md.getMissingChangesRS(serverId))));
-
-    // get the Server State
     ServerState state = md.getRSStates(serverId);
     if (state != null)
     {
-      AttributeBuilder builder = new AttributeBuilder("server-state");
-      builder.addAllStrings(state.toStringSet());
-      attributes.add(builder.toAttribute());
+      attributes.add("server-state", state.toStringSet());
     }
 
     return attributes;
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ServerHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ServerHandler.java
index e8f0112..4af0ae1 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ServerHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/ServerHandler.java
@@ -12,14 +12,13 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2006-2010 Sun Microsystems, Inc.
- * Portions Copyright 2011-2015 ForgeRock AS.
+ * Portions Copyright 2011-2016 ForgeRock AS.
  */
 package org.opends.server.replication.server;
 
 import static org.opends.messages.ReplicationMessages.*;
 
 import java.io.IOException;
-import java.util.List;
 import java.util.Random;
 import java.util.concurrent.Semaphore;
 import java.util.concurrent.TimeUnit;
@@ -30,15 +29,29 @@
 import org.forgerock.opendj.config.server.ConfigException;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.replication.common.AssuredMode;
 import org.opends.server.replication.common.CSN;
 import org.opends.server.replication.common.RSInfo;
 import org.opends.server.replication.common.ServerStatus;
-import org.opends.server.replication.protocol.*;
+import org.opends.server.replication.protocol.AckMsg;
+import org.opends.server.replication.protocol.ChangeTimeHeartbeatMsg;
+import org.opends.server.replication.protocol.HeartbeatThread;
+import org.opends.server.replication.protocol.MonitorMsg;
+import org.opends.server.replication.protocol.MonitorRequestMsg;
+import org.opends.server.replication.protocol.ProtocolVersion;
+import org.opends.server.replication.protocol.ReplServerStartMsg;
+import org.opends.server.replication.protocol.ReplicationMsg;
+import org.opends.server.replication.protocol.ResetGenerationIdMsg;
+import org.opends.server.replication.protocol.RoutableMsg;
+import org.opends.server.replication.protocol.Session;
+import org.opends.server.replication.protocol.StartMsg;
+import org.opends.server.replication.protocol.StartSessionMsg;
+import org.opends.server.replication.protocol.TopologyMsg;
+import org.opends.server.replication.protocol.UpdateMsg;
+import org.opends.server.replication.protocol.WindowMsg;
 import org.opends.server.replication.server.changelog.api.ChangelogException;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.Attributes;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.InitializationException;
 
@@ -472,58 +485,46 @@
     return heartbeatInterval;
   }
 
-  /** {@inheritDoc} */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
     // Get the generic ones
-    List<Attribute> attributes = super.getMonitorData();
+    MonitorData attributes = super.getMonitorData();
 
-    attributes.add(Attributes.create("server-id", String.valueOf(serverId)));
-    attributes.add(Attributes.create("domain-name", String.valueOf(getBaseDN())));
+    attributes.add("server-id", serverId);
+    attributes.add("domain-name", getBaseDN());
 
     // Deprecated
-    attributes.add(Attributes.create("max-waiting-changes", String
-        .valueOf(maxQueueSize)));
-    attributes.add(Attributes.create("sent-updates", String
-        .valueOf(getOutCount())));
-    attributes.add(Attributes.create("received-updates", String
-        .valueOf(getInCount())));
+    attributes.add("max-waiting-changes", maxQueueSize);
+    attributes.add("sent-updates", getOutCount());
+    attributes.add("received-updates", getInCount());
 
     // Assured counters
-    attributes.add(Attributes.create("assured-sr-received-updates", String
-        .valueOf(getAssuredSrReceivedUpdates())));
-    attributes.add(Attributes.create("assured-sr-received-updates-timeout",
-        String .valueOf(getAssuredSrReceivedUpdatesTimeout())));
-    attributes.add(Attributes.create("assured-sr-sent-updates", String
-        .valueOf(getAssuredSrSentUpdates())));
-    attributes.add(Attributes.create("assured-sr-sent-updates-timeout", String
-        .valueOf(getAssuredSrSentUpdatesTimeout())));
-    attributes.add(Attributes.create("assured-sd-received-updates", String
-        .valueOf(getAssuredSdReceivedUpdates())));
+    attributes.add("assured-sr-received-updates", getAssuredSrReceivedUpdates());
+    attributes.add("assured-sr-received-updates-timeout", getAssuredSrReceivedUpdatesTimeout());
+    attributes.add("assured-sr-sent-updates", getAssuredSrSentUpdates());
+    attributes.add("assured-sr-sent-updates-timeout", getAssuredSrSentUpdatesTimeout());
+    attributes.add("assured-sd-received-updates", getAssuredSdReceivedUpdates());
     if (!isDataServer())
     {
-      attributes.add(Attributes.create("assured-sd-sent-updates",
-          String.valueOf(getAssuredSdSentUpdates())));
-      attributes.add(Attributes.create("assured-sd-sent-updates-timeout",
-          String.valueOf(getAssuredSdSentUpdatesTimeout())));
+      attributes.add("assured-sd-sent-updates", getAssuredSdSentUpdates());
+      attributes.add("assured-sd-sent-updates-timeout", getAssuredSdSentUpdatesTimeout());
     } else
     {
-      attributes.add(Attributes.create("assured-sd-received-updates-timeout",
-          String.valueOf(getAssuredSdReceivedUpdatesTimeout())));
+      attributes.add("assured-sd-received-updates-timeout", getAssuredSdReceivedUpdatesTimeout());
     }
 
     // Window stats
-    attributes.add(Attributes.create("max-send-window", String.valueOf(sendWindowSize)));
-    attributes.add(Attributes.create("current-send-window", String.valueOf(sendWindow.availablePermits())));
-    attributes.add(Attributes.create("max-rcv-window", String.valueOf(maxRcvWindow)));
-    attributes.add(Attributes.create("current-rcv-window", String.valueOf(rcvWindow)));
+    attributes.add("max-send-window", sendWindowSize);
+    attributes.add("current-send-window", sendWindow.availablePermits());
+    attributes.add("max-rcv-window", maxRcvWindow);
+    attributes.add("current-rcv-window", rcvWindow);
 
     // Encryption
-    attributes.add(Attributes.create("ssl-encryption", String.valueOf(session.isEncrypted())));
+    attributes.add("ssl-encryption", session.isEncrypted());
 
     // Data generation
-    attributes.add(Attributes.create("generation-id", String.valueOf(generationId)));
+    attributes.add("generation-id", generationId);
 
     return attributes;
   }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileChangeNumberIndexDB.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileChangeNumberIndexDB.java
index 35b0feb..5671374 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileChangeNumberIndexDB.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileChangeNumberIndexDB.java
@@ -17,8 +17,6 @@
 
 import static org.opends.messages.ReplicationMessages.*;
 
-import java.util.ArrayList;
-import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
@@ -29,6 +27,7 @@
 import org.forgerock.opendj.ldap.ByteString;
 import org.forgerock.opendj.ldap.ByteStringBuilder;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.replication.common.CSN;
@@ -36,8 +35,6 @@
 import org.opends.server.replication.server.changelog.api.ChangeNumberIndexRecord;
 import org.opends.server.replication.server.changelog.api.ChangelogException;
 import org.opends.server.replication.server.changelog.api.DBCursor;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.Attributes;
 import org.forgerock.opendj.ldap.DN;
 import org.opends.server.types.InitializationException;
 
@@ -288,24 +285,19 @@
   private class DbMonitorProvider extends MonitorProvider<MonitorProviderCfg>
   {
     @Override
-    public List<Attribute> getMonitorData()
+    public MonitorData getMonitorData()
     {
       long firstCN = readChangeNumber(ChangeNumberType.FIRST);
       long lastCN = readChangeNumber(ChangeNumberType.LAST);
       long numberOfChanges = lastCN == NO_KEY ? 0 : lastCN - firstCN + 1;
 
-      final List<Attribute> attributes = new ArrayList<>();
-      attributes.add(toAttribute(ChangeNumberType.FIRST, firstCN));
-      attributes.add(toAttribute(ChangeNumberType.LAST, lastCN));
-      attributes.add(Attributes.create("count", Long.toString(numberOfChanges)));
+      final MonitorData attributes = new MonitorData(3);
+      attributes.add(ChangeNumberType.FIRST.getAttributeName(), firstCN);
+      attributes.add(ChangeNumberType.LAST.getAttributeName(), lastCN);
+      attributes.add("count", numberOfChanges);
       return attributes;
     }
 
-    private Attribute toAttribute(final ChangeNumberType cnType, long changeNumber)
-    {
-      return Attributes.create(cnType.getAttributeName(), String.valueOf(changeNumber));
-    }
-
     private long readChangeNumber(final ChangeNumberType type)
     {
       try
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileReplicaDB.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileReplicaDB.java
index f67cc4c..c746294 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileReplicaDB.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/server/changelog/file/FileReplicaDB.java
@@ -17,9 +17,7 @@
 
 import static org.opends.messages.ReplicationMessages.*;
 
-import java.util.ArrayList;
 import java.util.Date;
-import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import net.jcip.annotations.Immutable;
@@ -27,6 +25,7 @@
 import org.forgerock.opendj.config.server.ConfigException;
 import org.forgerock.opendj.ldap.ByteString;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.replication.common.CSN;
@@ -39,8 +38,6 @@
 import org.opends.server.replication.server.changelog.api.DBCursor.KeyMatchingStrategy;
 import org.opends.server.replication.server.changelog.api.DBCursor.PositionStrategy;
 import org.opends.server.replication.server.changelog.file.Log.RepositionableCursor;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.Attributes;
 import org.forgerock.opendj.ldap.DN;
 import org.opends.server.types.InitializationException;
 
@@ -250,30 +247,24 @@
    */
   private class DbMonitorProvider extends MonitorProvider<MonitorProviderCfg>
   {
-    /** {@inheritDoc} */
     @Override
-    public List<Attribute> getMonitorData()
+    public MonitorData getMonitorData()
     {
-      final List<Attribute> attributes = new ArrayList<>();
-      create(attributes, "replicationServer-database",String.valueOf(serverId));
-      create(attributes, "domain-name", baseDN.toString());
+      final MonitorData attributes = new MonitorData(4);
+      attributes.add("replicationServer-database", serverId);
+      attributes.add("domain-name", baseDN);
       final CSNLimits limits = csnLimits;
       if (limits.oldestCSN != null)
       {
-        create(attributes, "first-change", encode(limits.oldestCSN));
+        attributes.add("first-change", encode(limits.oldestCSN));
       }
       if (limits.newestCSN != null)
       {
-        create(attributes, "last-change", encode(limits.newestCSN));
+        attributes.add("last-change", encode(limits.newestCSN));
       }
       return attributes;
     }
 
-    private void create(final List<Attribute> attributes, final String name, final String value)
-    {
-      attributes.add(Attributes.create(name, value));
-    }
-
     private String encode(final CSN csn)
     {
       return csn + " " + new Date(csn.getTime());
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationDomain.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationDomain.java
index 8c456cf..54ab267 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationDomain.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationDomain.java
@@ -26,9 +26,7 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.net.SocketTimeoutException;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
@@ -51,12 +49,35 @@
 import org.opends.server.admin.std.meta.ReplicationDomainCfgDefn.AssuredType;
 import org.opends.server.admin.std.server.ReplicationDomainCfg;
 import org.opends.server.api.DirectoryThread;
+import org.opends.server.api.MonitorData;
 import org.opends.server.backends.task.Task;
-import org.opends.server.replication.common.*;
-import org.opends.server.replication.protocol.*;
+import org.opends.server.replication.common.AssuredMode;
+import org.opends.server.replication.common.CSN;
+import org.opends.server.replication.common.CSNGenerator;
+import org.opends.server.replication.common.DSInfo;
+import org.opends.server.replication.common.RSInfo;
+import org.opends.server.replication.common.ServerState;
+import org.opends.server.replication.common.ServerStatus;
+import org.opends.server.replication.common.StatusMachine;
+import org.opends.server.replication.common.StatusMachineEvent;
+import org.opends.server.replication.protocol.AckMsg;
+import org.opends.server.replication.protocol.ChangeStatusMsg;
+import org.opends.server.replication.protocol.DoneMsg;
+import org.opends.server.replication.protocol.EntryMsg;
+import org.opends.server.replication.protocol.ErrorMsg;
+import org.opends.server.replication.protocol.HeartbeatMsg;
+import org.opends.server.replication.protocol.InitializeRcvAckMsg;
+import org.opends.server.replication.protocol.InitializeRequestMsg;
+import org.opends.server.replication.protocol.InitializeTargetMsg;
+import org.opends.server.replication.protocol.ProtocolVersion;
+import org.opends.server.replication.protocol.ReplSessionSecurity;
+import org.opends.server.replication.protocol.ReplicationMsg;
+import org.opends.server.replication.protocol.ResetGenerationIdMsg;
+import org.opends.server.replication.protocol.RoutableMsg;
+import org.opends.server.replication.protocol.TopologyMsg;
+import org.opends.server.replication.protocol.UpdateMsg;
 import org.opends.server.tasks.InitializeTargetTask;
 import org.opends.server.tasks.InitializeTask;
-import org.opends.server.types.Attribute;
 import org.forgerock.opendj.ldap.DN;
 import org.opends.server.types.DirectoryException;
 
@@ -3430,12 +3451,10 @@
    * Subclasses should use this method to add additional monitoring information
    * in the ReplicationDomain.
    *
-   * @return Additional monitoring attributes that will be added in the
-   *         ReplicationDomain monitoring entry.
+   * @param monitorData where to additional monitoring attributes
    */
-  public Collection<Attribute> getAdditionalMonitoring()
+  public void addAdditionalMonitoring(MonitorData monitorData)
   {
-    return new ArrayList<>();
   }
 
   /**
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationMonitor.java b/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationMonitor.java
index 17b79e3..ed6d4bd 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationMonitor.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/replication/service/ReplicationMonitor.java
@@ -12,21 +12,19 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2006-2010 Sun Microsystems, Inc.
- * Portions copyright 2013-2015 ForgeRock AS.
+ * Portions copyright 2013-2016 ForgeRock AS.
  */
 package org.opends.server.replication.service;
 
 import java.util.ArrayList;
-import java.util.List;
+import java.util.Collection;
 import java.util.Map;
 import java.util.Map.Entry;
 
 import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
 import org.opends.server.replication.service.ReplicationDomain.ImportExportContext;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeBuilder;
-import org.opends.server.types.Attributes;
 
 /**
  * Class used to generate monitoring information for the replication.
@@ -66,111 +64,83 @@
         + ",cn=Replication";
   }
 
-  /**
-   * Retrieves a set of attributes containing monitor data that should be
-   * returned to the client if the corresponding monitor entry is requested.
-   *
-   * @return  A set of attributes containing monitor data that should be
-   *          returned to the client if the corresponding monitor entry is
-   *          requested.
-   */
   @Override
-  public List<Attribute> getMonitorData()
+  public MonitorData getMonitorData()
   {
-    List<Attribute> attributes = new ArrayList<>();
+    final MonitorData attributes = new MonitorData(41);
 
-    addMonitorData(attributes, "domain-name", domain.getBaseDN());
-    addMonitorData(attributes, "connected-to", domain.getReplicationServer());
-    addMonitorData(attributes, "lost-connections", domain.getNumLostConnections());
-    addMonitorData(attributes, "received-updates", domain.getNumRcvdUpdates());
-    addMonitorData(attributes, "sent-updates", domain.getNumSentUpdates());
+    attributes.add("domain-name", domain.getBaseDN());
+    attributes.add("server-id", domain.getServerId());
+    attributes.add("connected-to", domain.getReplicationServer());
+    attributes.add("lost-connections", domain.getNumLostConnections());
 
-    // get number of changes replayed
-    addMonitorData(attributes, "replayed-updates", domain.getNumProcessedUpdates());
-
-    addMonitorData(attributes, "server-id", domain.getServerId());
+    attributes.add("received-updates", domain.getNumRcvdUpdates());
+    attributes.add("sent-updates", domain.getNumSentUpdates());
+    attributes.add("replayed-updates", domain.getNumProcessedUpdates());
 
     // get window information
-    addMonitorData(attributes, "max-rcv-window", domain.getMaxRcvWindow());
-    addMonitorData(attributes, "current-rcv-window", domain.getCurrentRcvWindow());
-    addMonitorData(attributes, "max-send-window", domain.getMaxSendWindow());
-    addMonitorData(attributes, "current-send-window", domain.getCurrentSendWindow());
+    attributes.add("max-rcv-window", domain.getMaxRcvWindow());
+    attributes.add("current-rcv-window", domain.getCurrentRcvWindow());
+    attributes.add("max-send-window", domain.getMaxSendWindow());
+    attributes.add("current-send-window", domain.getCurrentSendWindow());
 
-    // get the Server State
-    final String ATTR_SERVER_STATE = "server-state";
-    AttributeBuilder builder = new AttributeBuilder(ATTR_SERVER_STATE);
-    builder.addAllStrings(domain.getServerState().toStringSet());
-    attributes.add(builder.toAttribute());
-
-    addMonitorData(attributes, "ssl-encryption", domain.isSessionEncrypted());
-    addMonitorData(attributes, "generation-id", domain.getGenerationID());
+    attributes.add("server-state", domain.getServerState().toStringSet());
+    attributes.add("ssl-encryption", domain.isSessionEncrypted());
+    attributes.add("generation-id", domain.getGenerationID());
 
     // Add import/export monitoring attributes
     final ImportExportContext ieContext = domain.getImportExportContext();
     if (ieContext != null)
     {
-      addMonitorData(attributes, "total-update", ieContext.importInProgress() ? "import" : "export");
-      addMonitorData(attributes, "total-update-entry-count", ieContext.getTotalEntryCount());
-      addMonitorData(attributes, "total-update-entry-left", ieContext.getLeftEntryCount());
+      attributes.add("total-update", ieContext.importInProgress() ? "import" : "export");
+      attributes.add("total-update-entry-count", ieContext.getTotalEntryCount());
+      attributes.add("total-update-entry-left", ieContext.getLeftEntryCount());
     }
 
 
     // Add the concrete Domain attributes
-    attributes.addAll(domain.getAdditionalMonitoring());
+    domain.addAdditionalMonitoring(attributes);
 
     /*
      * Add assured replication related monitoring fields
      * (see domain.getXXX() method comment for field meaning)
      */
-    addMonitorData(attributes, "assured-sr-sent-updates", domain.getAssuredSrSentUpdates());
-    addMonitorData(attributes, "assured-sr-acknowledged-updates", domain.getAssuredSrAcknowledgedUpdates());
-    addMonitorData(attributes, "assured-sr-not-acknowledged-updates", domain.getAssuredSrNotAcknowledgedUpdates());
-    addMonitorData(attributes, "assured-sr-timeout-updates", domain.getAssuredSrTimeoutUpdates());
-    addMonitorData(attributes, "assured-sr-wrong-status-updates", domain.getAssuredSrWrongStatusUpdates());
-    addMonitorData(attributes, "assured-sr-replay-error-updates", domain.getAssuredSrReplayErrorUpdates());
-    addMonitorData(attributes, "assured-sr-server-not-acknowledged-updates", domain
-        .getAssuredSrServerNotAcknowledgedUpdates());
-    addMonitorData(attributes, "assured-sr-received-updates", domain.getAssuredSrReceivedUpdates());
-    addMonitorData(attributes, "assured-sr-received-updates-acked", domain.getAssuredSrReceivedUpdatesAcked());
-    addMonitorData(attributes, "assured-sr-received-updates-not-acked", domain.getAssuredSrReceivedUpdatesNotAcked());
-    addMonitorData(attributes, "assured-sd-sent-updates", domain.getAssuredSdSentUpdates());
-    addMonitorData(attributes, "assured-sd-acknowledged-updates", domain.getAssuredSdAcknowledgedUpdates());
-    addMonitorData(attributes, "assured-sd-timeout-updates", domain.getAssuredSdTimeoutUpdates());
+    attributes.add("assured-sr-sent-updates", domain.getAssuredSrSentUpdates());
+    attributes.add("assured-sr-acknowledged-updates", domain.getAssuredSrAcknowledgedUpdates());
+    attributes.add("assured-sr-not-acknowledged-updates", domain.getAssuredSrNotAcknowledgedUpdates());
+    attributes.add("assured-sr-timeout-updates", domain.getAssuredSrTimeoutUpdates());
+    attributes.add("assured-sr-wrong-status-updates", domain.getAssuredSrWrongStatusUpdates());
+    attributes.add("assured-sr-replay-error-updates", domain.getAssuredSrReplayErrorUpdates());
+    addMonitorData(attributes,
+        "assured-sr-server-not-acknowledged-updates",
+        domain.getAssuredSrServerNotAcknowledgedUpdates());
+    attributes.add("assured-sr-received-updates", domain.getAssuredSrReceivedUpdates());
+    attributes.add("assured-sr-received-updates-acked", domain.getAssuredSrReceivedUpdatesAcked());
+    attributes.add("assured-sr-received-updates-not-acked", domain.getAssuredSrReceivedUpdatesNotAcked());
+    attributes.add("assured-sd-sent-updates", domain.getAssuredSdSentUpdates());
+    attributes.add("assured-sd-acknowledged-updates", domain.getAssuredSdAcknowledgedUpdates());
+    attributes.add("assured-sd-timeout-updates", domain.getAssuredSdTimeoutUpdates());
     addMonitorData(attributes, "assured-sd-server-timeout-updates", domain.getAssuredSdServerTimeoutUpdates());
 
     // Status related monitoring fields
-    addMonitorData(attributes, "last-status-change-date", domain.getLastStatusChangeDate());
-
-    addMonitorData(attributes, "status", domain.getStatus());
+    attributes.add("last-status-change-date", domain.getLastStatusChangeDate());
+    attributes.add("status", domain.getStatus());
 
     return attributes;
   }
 
-  private void addMonitorData(List<Attribute> attributes, String attrName,
-      Map<Integer, Integer> serverIdToNb)
+  private void addMonitorData(MonitorData attributes, String attrName, Map<Integer, Integer> serverIdToNb)
   {
     if (!serverIdToNb.isEmpty())
     {
-      final AttributeBuilder builder = new AttributeBuilder(attrName);
+      Collection<String> values = new ArrayList<>();
       for (Entry<Integer, Integer> entry : serverIdToNb.entrySet())
       {
         final Integer serverId = entry.getKey();
         final Integer nb = entry.getValue();
-        builder.add(serverId + ":" + nb);
+        values.add(serverId + ":" + nb);
       }
-      attributes.add(builder.toAttribute());
+      attributes.add(attrName, values);
     }
   }
-
-  /**
-   * Adds an attribute with a value to the list of monitoring attributes.
-   *
-   * @param attributes the list of monitoring attributes
-   * @param attrName the name of the attribute to add.
-   * @param value The value of he attribute to add.
-   */
-  public static void addMonitorData(List<Attribute> attributes, String attrName, Object value)
-  {
-    attributes.add(Attributes.create(attrName, String.valueOf(value)));
-  }
 }
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/monitors/TestMonitorProvider.java b/opendj-server-legacy/src/test/java/org/opends/server/monitors/TestMonitorProvider.java
index f8452d8..2d20e54 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/monitors/TestMonitorProvider.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/monitors/TestMonitorProvider.java
@@ -12,38 +12,38 @@
  * information: "Portions Copyright [year] [name of copyright owner]".
  *
  * Copyright 2006-2010 Sun Microsystems, Inc.
- * Portions Copyright 2014 ForgeRock AS.
+ * Portions Copyright 2014-2016 ForgeRock AS.
  */
 
 package org.opends.server.monitors;
 
-import org.opends.server.admin.std.server.MonitorProviderCfg;
-import org.opends.server.api.MonitorProvider;
 import org.forgerock.opendj.config.server.ConfigException;
+import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.MonitorData;
+import org.opends.server.api.MonitorProvider;
 import org.opends.server.types.InitializationException;
-import org.opends.server.types.Attribute;
-
-import java.util.List;
-import java.util.Collections;
 
 /**
  * This test monitor provider has a DN embedded in its instance name.
  */
 class TestMonitorProvider extends MonitorProvider<MonitorProviderCfg>
 {
+  @Override
   public void initializeMonitorProvider(MonitorProviderCfg configuration)
        throws ConfigException, InitializationException
   {
     // No implementation required.
   }
 
+  @Override
   public String getMonitorInstanceName()
   {
     return "Test monitor for dc=example,dc=com";
   }
 
-  public List<Attribute> getMonitorData()
+  @Override
+  public MonitorData getMonitorData()
   {
-    return Collections.emptyList();
+    return new MonitorData(0);
   }
 }
diff --git a/opendj-server-legacy/src/test/java/org/opends/server/replication/StressTest.java b/opendj-server-legacy/src/test/java/org/opends/server/replication/StressTest.java
index 4f41050..90f7960 100644
--- a/opendj-server-legacy/src/test/java/org/opends/server/replication/StressTest.java
+++ b/opendj-server-legacy/src/test/java/org/opends/server/replication/StressTest.java
@@ -30,6 +30,7 @@
 import org.forgerock.opendj.ldap.ResultCode;
 import org.opends.server.TestCaseUtils;
 import org.opends.server.admin.std.server.MonitorProviderCfg;
+import org.opends.server.api.MonitorData;
 import org.opends.server.api.MonitorProvider;
 import org.opends.server.core.AddOperation;
 import org.opends.server.core.DirectoryServer;
@@ -38,34 +39,29 @@
 import org.opends.server.replication.protocol.AddMsg;
 import org.opends.server.replication.protocol.ReplicationMsg;
 import org.opends.server.replication.service.ReplicationBroker;
-import org.opends.server.types.*;
+import org.opends.server.types.Entry;
+import org.opends.server.types.InitializationException;
+import org.opends.server.types.Modification;
+import org.opends.server.types.Operation;
+import org.opends.server.types.OperationType;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
-/**
- * Stress test for the synchronization code using the ReplicationBroker API.
- */
+/** Stress test for the synchronization code using the ReplicationBroker API. */
 @SuppressWarnings("javadoc")
 public class StressTest extends ReplicationTestCase
 {
-
   private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
 
-
-  private static final String REPLICATION_STRESS_TEST =
-    "Replication Stress Test";
+  private static final String REPLICATION_STRESS_TEST = "Replication Stress Test";
 
   private BrokerReader reader;
-
   /** A "person" entry. */
   private Entry personEntry;
-
   private int replServerPort;
 
 
-  /**
-   * Stress test from LDAP server to client using the ReplicationBroker API.
-   */
+  /** Stress test from LDAP server to client using the ReplicationBroker API. */
   @Test(enabled=false, groups="slow")
   public void fromServertoBroker() throws Exception
   {
@@ -210,7 +206,6 @@
       this.count = count;
     }
 
-    /** {@inheritDoc} */
     @Override
     public void run()
     {
@@ -236,17 +231,14 @@
   {
     private ReplicationBroker broker;
     private int count;
-    private Boolean finished = false;
+    private boolean finished;
 
-    /**
-     * Creates a new Stress Test Reader.
-     */
+    /** Creates a new Stress Test Reader. */
     public BrokerReader(ReplicationBroker broker)
     {
       this.broker = broker;
     }
 
-    /** {@inheritDoc} */
     @Override
     public void run()
     {
@@ -307,13 +299,19 @@
   private class Monitor extends MonitorProvider<MonitorProviderCfg>
   {
     @Override
-    public List<Attribute> getMonitorData()
+    public MonitorData getMonitorData()
     {
-      String value = reader != null ? String.valueOf(reader.getCurrentCount()) : "not yet started";
-      List<Attribute> list = new LinkedList<>();
-      list.add(Attributes.create("received-messages", value));
-      list.add(Attributes.create("base-dn", "ou=People," + TEST_ROOT_DN_STRING));
-      return list;
+      MonitorData attrs = new MonitorData(2);
+      if (reader != null)
+      {
+        attrs.add("received-messages", reader.getCurrentCount());
+      }
+      else
+      {
+        attrs.add("received-messages", "not yet started");
+      }
+      attrs.add("base-dn", "ou=People," + TEST_ROOT_DN_STRING);
+      return attrs;
     }
 
     @Override
@@ -327,10 +325,6 @@
     throws ConfigException, InitializationException
     {
       // nothing to do
-
     }
-
-
-
   }
 }

--
Gitblit v1.10.0