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

sijie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/bookkeeper.git


The following commit(s) were added to refs/heads/master by this push:
     new cf29365  BOOKKEEPER-935: Javadoc improvements and publish sources and 
javadocs to Maven Central
cf29365 is described below

commit cf2936548aa7f91e99bb53a8d53cbca567649535
Author: Sijie Guo <[email protected]>
AuthorDate: Fri Jul 28 11:12:37 2017 -0700

    BOOKKEEPER-935: Javadoc improvements and publish sources and javadocs to 
Maven Central
    
    Descriptions of the changes in this PR:
    
    - sources: attached source jar for each module
    - javadocs: attached javdocs jar for bookkeeper-server, bookkeeper-stats 
(they are client-facing modules)
    
    for javadocs:
    - improve javadoc:aggregate to generate new client-facing api doc. it is 
comprised with 3 sections now : bookkeeper client, bookkeeper stats api, 
bookkeeper stats providers
    - auditing the client package to make changes to avoid expose internal 
classes to public.
    - introduce interface audience and stability for documenting public 
interfaces
    - improve javadoc for publish api
    
    Author: Sijie Guo <[email protected]>
    
    Reviewers: Enrico Olivelli <[email protected]>, Matteo Merli 
<[email protected]>
    
    This patch had conflicts when merged, resolved by
    Committer: Sijie Guo <[email protected]>
    
    This closes #311 from sijie/attach_sources_jar
---
 bookkeeper-server/pom.xml                          |  24 +++
 .../auth/AuthProviderFactoryFactory.java           |   4 +-
 .../apache/bookkeeper/auth/BookieAuthProvider.java |   3 +-
 .../apache/bookkeeper/auth/ClientAuthProvider.java |   2 +-
 .../bookie/LocalBookieEnsemblePlacementPolicy.java |   9 +-
 .../apache/bookkeeper/client/AsyncCallback.java    | 119 ++++++++++--
 .../org/apache/bookkeeper/client/BKException.java  |  71 ++++++-
 .../org/apache/bookkeeper/client/BookKeeper.java   | 100 +++++++++-
 .../bookkeeper/client/BookKeeperClientStats.java   |   3 +
 .../apache/bookkeeper/client/BookieInfoReader.java |  11 ++
 .../apache/bookkeeper/client/BookiesListener.java  |  12 +-
 .../client/DefaultEnsemblePlacementPolicy.java     |   4 +-
 .../DefaultSpeculativeRequestExecutionPolicy.java  |   6 +
 .../bookkeeper/client/EnsemblePlacementPolicy.java | 215 +++++++++++++++++++--
 .../ITopologyAwareEnsemblePlacementPolicy.java     |  13 +-
 .../apache/bookkeeper/client/LedgerChecker.java    |   4 +-
 .../apache/bookkeeper/client/LedgerMetadata.java   |   3 +-
 .../apache/bookkeeper/client/MacDigestManager.java |   8 +-
 .../client/RackawareEnsemblePlacementPolicy.java   |   5 +
 .../client/ReadLastConfirmedAndEntryOp.java        |  61 ++----
 .../client/RegionAwareEnsemblePlacementPolicy.java |   5 +
 .../client/SpeculativeRequestExecutionPolicy.java  |   8 +
 .../client/SpeculativeRequestExecutor.java         |   8 +
 .../bookkeeper/client/SynchCallbackUtils.java      |   2 +-
 .../bookkeeper/client/WeightedRandomSelection.java |   2 +-
 ...ClientConnectionPeer.java => package-info.java} |  12 +-
 .../common/annotation/InterfaceAudience.java       |  56 ++++++
 .../common/annotation/InterfaceStability.java      |  51 +++++
 .../annotation/package-info.java}                  |  13 +-
 .../package-info.java}                             |  15 +-
 .../org/apache/bookkeeper/proto/AuthHandler.java   |   2 -
 .../{bookie => proto}/BookieConnectionPeer.java    |   4 +-
 .../apache/bookkeeper/proto/BookieNettyServer.java |   1 -
 .../{client => proto}/ClientConnectionPeer.java    |   4 +-
 .../bookkeeper/proto/PerChannelBookieClient.java   |  28 +--
 .../proto/ReadLastConfirmedAndEntryContext.java    |  66 +++++++
 .../bookkeeper/replication/ReplicationWorker.java  |   4 +-
 .../bookkeeper/sasl/SASLBookieAuthProvider.java    |   2 +-
 .../sasl/SASLBookieAuthProviderFactory.java        |   2 +-
 .../bookkeeper/sasl/SASLClientAuthProvider.java    |   2 +-
 .../bookkeeper/sasl/SASLClientProviderFactory.java |   2 +-
 .../java/org/apache/bookkeeper/auth/TestAuth.java  |   4 +-
 .../replication/AuthAutoRecoveryTest.java          |   2 +-
 bookkeeper-stats/pom.xml                           |  24 +++
 pom.xml                                            |  33 +++-
 45 files changed, 847 insertions(+), 182 deletions(-)

diff --git a/bookkeeper-server/pom.xml b/bookkeeper-server/pom.xml
index d7babbd..8647d5e 100644
--- a/bookkeeper-server/pom.xml
+++ b/bookkeeper-server/pom.xml
@@ -374,6 +374,30 @@
           </filesets>
        </configuration>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>${maven-javadoc-plugin.version}</version>
+        <configuration>
+          <!-- Avoid for missing javadoc comments to be marked as errors -->
+          <additionalparam>-Xdoclint:none</additionalparam>
+          
<subpackages>org.apache.bookkeeper.client:org.apache.bookkeeper.common.annotation:org.apache.bookkeeper.conf:org.apache.bookkeeper.feature:org.apache.bookkeeper.stats</subpackages>
+          <groups>
+            <group>
+              <title>Bookkeeper</title>
+              <packages>org.apache.bookkeeper*</packages>
+            </group>
+          </groups>
+        </configuration>
+        <executions>
+          <execution>
+            <id>attach-javadocs</id>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
     </plugins>
   </build>
   <profiles>
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/AuthProviderFactoryFactory.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/AuthProviderFactoryFactory.java
index 9ead4c2..4aff5b3 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/AuthProviderFactoryFactory.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/AuthProviderFactoryFactory.java
@@ -26,8 +26,8 @@ import org.apache.bookkeeper.client.BKException;
 import org.apache.bookkeeper.conf.ClientConfiguration;
 import org.apache.bookkeeper.conf.ServerConfiguration;
 import org.apache.bookkeeper.util.ReflectionUtils;
-import org.apache.bookkeeper.client.ClientConnectionPeer;
-import org.apache.bookkeeper.bookie.BookieConnectionPeer;
+import org.apache.bookkeeper.proto.ClientConnectionPeer;
+import org.apache.bookkeeper.proto.BookieConnectionPeer;
 
 /**
  * A factory to manage the authentication provider factories.
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/BookieAuthProvider.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/BookieAuthProvider.java
index 8de0af2..4132fb6 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/BookieAuthProvider.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/BookieAuthProvider.java
@@ -23,8 +23,7 @@ package org.apache.bookkeeper.auth;
 import java.io.IOException;
 
 import org.apache.bookkeeper.conf.ServerConfiguration;
-import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.GenericCallback;
-import org.apache.bookkeeper.bookie.BookieConnectionPeer;
+import org.apache.bookkeeper.proto.BookieConnectionPeer;
 
 /**
  * Bookie authentication provider interface.
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/ClientAuthProvider.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/ClientAuthProvider.java
index 318541c..9f60cac 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/ClientAuthProvider.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/auth/ClientAuthProvider.java
@@ -23,7 +23,7 @@ package org.apache.bookkeeper.auth;
 import java.io.IOException;
 
 import org.apache.bookkeeper.conf.ClientConfiguration;
-import org.apache.bookkeeper.client.ClientConnectionPeer;
+import org.apache.bookkeeper.proto.ClientConnectionPeer;
 
 /**
  * Client authentication provider interface.
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LocalBookieEnsemblePlacementPolicy.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LocalBookieEnsemblePlacementPolicy.java
index e4ab92b..18057f0 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LocalBookieEnsemblePlacementPolicy.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/LocalBookieEnsemblePlacementPolicy.java
@@ -17,14 +17,15 @@
  */
 package org.apache.bookkeeper.bookie;
 
+import io.netty.util.HashedWheelTimer;
 import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
-
 import org.apache.bookkeeper.client.BookieInfoReader.BookieInfo;
 import org.apache.bookkeeper.client.EnsemblePlacementPolicy;
 import org.apache.bookkeeper.client.BKException.BKNotEnoughBookiesException;
@@ -35,15 +36,13 @@ import org.apache.bookkeeper.net.BookieSocketAddress;
 import org.apache.bookkeeper.net.DNSToSwitchMapping;
 import org.apache.bookkeeper.stats.StatsLogger;
 import com.google.common.collect.Lists;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import io.netty.util.HashedWheelTimer;
-import java.util.Optional;
-
 /**
  * Special ensemble placement policy that always return local bookie. Only 
works with ledgers with ensemble=1.
+ *
+ * @see EnsemblePlacementPolicy
  */
 public class LocalBookieEnsemblePlacementPolicy implements 
EnsemblePlacementPolicy {
 
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/AsyncCallback.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/AsyncCallback.java
index 8f5bdea..200bb47 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/AsyncCallback.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/AsyncCallback.java
@@ -1,7 +1,3 @@
-package org.apache.bookkeeper.client;
-
-import java.util.Enumeration;
-
 /**
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements. See the NOTICE file distributed with this
@@ -18,9 +14,27 @@ import java.util.Enumeration;
  * License for the specific language governing permissions and limitations 
under
  * the License.
  */
+package org.apache.bookkeeper.client;
+
+import java.util.Enumeration;
+import org.apache.bookkeeper.common.annotation.InterfaceAudience;
+import org.apache.bookkeeper.common.annotation.InterfaceStability;
 
+/**
+ * Defines all the callback interfaces for the async operations in bookkeeper 
client.
+ */
[email protected]
[email protected]
 public interface AsyncCallback {
-    public interface AddCallback {
+
+    /**
+     * Async Callback for adding entries to ledgers.
+     *
+     * @since 4.0
+     */
+    @InterfaceAudience.Public
+    @InterfaceStability.Stable
+    interface AddCallback {
         /**
          * Callback declaration
          *
@@ -36,7 +50,14 @@ public interface AsyncCallback {
         void addComplete(int rc, LedgerHandle lh, long entryId, Object ctx);
     }
 
-    public interface AddLacCallback {
+    /**
+     * Async Callback for updating LAC for ledgers.
+     *
+     * @since 4.5
+     */
+    @InterfaceAudience.Public
+    @InterfaceStability.Stable
+    interface AddLacCallback {
         /**
          * Callback declaration
          *
@@ -50,7 +71,14 @@ public interface AsyncCallback {
         void addLacComplete(int rc, LedgerHandle lh, Object ctx);
     }
 
-    public interface CloseCallback {
+    /**
+     * Async Callback for closing ledgers.
+     *
+     * @since 4.0
+     */
+    @InterfaceAudience.Public
+    @InterfaceStability.Stable
+    interface CloseCallback {
         /**
          * Callback definition
          *
@@ -64,7 +92,14 @@ public interface AsyncCallback {
         void closeComplete(int rc, LedgerHandle lh, Object ctx);
     }
 
-    public interface CreateCallback {
+    /**
+     * Async Callback for creating ledgers.
+     *
+     * @since 4.0
+     */
+    @InterfaceAudience.Public
+    @InterfaceStability.Stable
+    interface CreateCallback {
         /**
          * Declaration of callback method
          *
@@ -75,11 +110,17 @@ public interface AsyncCallback {
          * @param ctx
          *          context object
          */
-
         void createComplete(int rc, LedgerHandle lh, Object ctx);
     }
 
-    public interface OpenCallback {
+    /**
+     * Async Callback for opening ledgers.
+     *
+     * @since 4.0
+     */
+    @InterfaceAudience.Public
+    @InterfaceStability.Stable
+    interface OpenCallback {
         /**
          * Callback for asynchronous call to open ledger
          *
@@ -90,12 +131,18 @@ public interface AsyncCallback {
          * @param ctx
          *          context object
          */
-
-        public void openComplete(int rc, LedgerHandle lh, Object ctx);
+        void openComplete(int rc, LedgerHandle lh, Object ctx);
 
     }
 
-    public interface ReadCallback {
+    /**
+     * Async Callback for reading entries from ledgers.
+     *
+     * @since 4.0
+     */
+    @InterfaceAudience.Public
+    @InterfaceStability.Stable
+    interface ReadCallback {
         /**
          * Callback declaration
          *
@@ -108,12 +155,18 @@ public interface AsyncCallback {
          * @param ctx
          *          context object
          */
-
         void readComplete(int rc, LedgerHandle lh, Enumeration<LedgerEntry> 
seq,
                           Object ctx);
     }
 
-    public interface DeleteCallback {
+    /**
+     * Async Callback for deleting ledgers.
+     *
+     * @since 4.0
+     */
+    @InterfaceAudience.Public
+    @InterfaceStability.Stable
+    interface DeleteCallback {
         /**
          * Callback definition for delete operations
          *
@@ -125,7 +178,14 @@ public interface AsyncCallback {
         void deleteComplete(int rc, Object ctx);
     }
 
-    public interface ReadLastConfirmedCallback {
+    /**
+     * Async Callback for reading LAC for ledgers.
+     *
+     * @since 4.0
+     */
+    @InterfaceAudience.Public
+    @InterfaceStability.Stable
+    interface ReadLastConfirmedCallback {
         /**
          * Callback definition for bookie recover operations
          *
@@ -139,7 +199,14 @@ public interface AsyncCallback {
         void readLastConfirmedComplete(int rc, long lastConfirmed, Object ctx);
     }
 
-    public interface ReadLastConfirmedAndEntryCallback {
+    /**
+     * Async Callback for long polling read request.
+     *
+     * @since 4.5
+     */
+    @InterfaceAudience.Public
+    @InterfaceStability.Stable
+    interface ReadLastConfirmedAndEntryCallback {
         /**
          * Callback definition for bookie operation that allows reading the 
last add confirmed
          * along with an entry within the last add confirmed range
@@ -155,7 +222,14 @@ public interface AsyncCallback {
         void readLastConfirmedAndEntryComplete(int rc, long lastConfirmed, 
LedgerEntry entry, Object ctx);
     }
 
-    public interface RecoverCallback {
+    /**
+     * Async Callback for recovering ledgers.
+     *
+     * @since 4.0
+     */
+    @InterfaceAudience.Public
+    @InterfaceStability.Stable
+    interface RecoverCallback {
         /**
          * Callback definition for bookie recover operations
          *
@@ -167,7 +241,14 @@ public interface AsyncCallback {
         void recoverComplete(int rc, Object ctx);
     }
     
-    public interface IsClosedCallback {
+    /**
+     * Async Callback for checking if a ledger is closed.
+     *
+     * @since 4.0
+     */
+    @InterfaceAudience.Public
+    @InterfaceStability.Stable
+    interface IsClosedCallback {
         /**
          * Callback definition for isClosed operation
          *
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BKException.java 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BKException.java
index e17d8b9..1c4cec8 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BKException.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BKException.java
@@ -1,5 +1,3 @@
-package org.apache.bookkeeper.client;
-
 /*
  *
  * Licensed to the Apache Software Foundation (ASF) under one
@@ -20,6 +18,7 @@ package org.apache.bookkeeper.client;
  * under the License.
  *
  */
+package org.apache.bookkeeper.client;
 
 import java.lang.Exception;
 
@@ -110,48 +109,108 @@ public abstract class BKException extends Exception {
     }
 
     /**
-     * List of return codes
-     *
+     * Codes which represent the various {@link BKException} types.
      */
     public interface Code {
+        /** A placer holder (unused) */
         int UNINITIALIZED = 1;
+        /** Everything is OK */
         int OK = 0;
+        /** Read operations failed (bookie error) */
         int ReadException = -1;
+        /** Unused */
         int QuorumException = -2;
+        /** Unused */
         int NoBookieAvailableException = -3;
+        /** Digest Manager is not initialized (client error) */
         int DigestNotInitializedException = -4;
+        /** Digest doesn't match on returned entries */
         int DigestMatchException = -5;
+        /** Not enough bookies available to form an ensemble */
         int NotEnoughBookiesException = -6;
+        /** No such ledger exists */
         int NoSuchLedgerExistsException = -7;
+        /** Bookies are not available */
         int BookieHandleNotAvailableException = -8;
+        /** ZooKeeper operations failed */
         int ZKException = -9;
+        /** Ledger recovery operations failed */
         int LedgerRecoveryException = -10;
+        /** Executing operations on a closed ledger handle */
         int LedgerClosedException = -11;
+        /** Write operations failed (bookie error) */
         int WriteException = -12;
+        /** No such entry exists */
         int NoSuchEntryException = -13;
+        /** Incorrect parameters (operations are absolutely not executed) */
         int IncorrectParameterException = -14;
+        /** Synchronous operations are interrupted */
         int InterruptedException = -15;
+        /** Protocol version is wrong (operations are absolutely not executed) 
*/
         int ProtocolVersionException = -16;
+        /** Bad version on executing metadata operations */
         int MetadataVersionException = -17;
+        /** Meta store operations failed */
         int MetaStoreException = -18;
+        /** Executing operations on a closed client */
         int ClientClosedException = -19;
+        /** Ledger already exists */
         int LedgerExistException = -20;
+        /**
+         * Add entry operation timeouts on waiting quorum responses.
+         *
+         * @since 4.5
+         */
         int AddEntryQuorumTimeoutException = -21;
+        /**
+         * Duplicated entry id is found when {@link 
LedgerHandleAdv#addEntry(long, byte[])}.
+         *
+         * @since 4.5
+         */
         int DuplicateEntryIdException = -22;
+        /**
+         * Operations timeouts.
+         *
+         * @since 4.5
+         */
         int TimeoutException = -23;
 
+        /**
+         * Operation is illegal.
+         */
         int IllegalOpException = -100;
+        /**
+         * Operations failed due to ledgers are fenced.
+         */
         int LedgerFencedException = -101;
+        /**
+         * Operations failed due to unauthorized.
+         */
         int UnauthorizedAccessException = -102;
+        /**
+         * Replication failed due to unclosed fragments.
+         */
         int UnclosedFragmentException = -103;
+        /**
+         * Write operations failed due to bookies are readonly
+         */
         int WriteOnReadOnlyBookieException = -104;
         //-105 reserved for TooManyRequestsException
+        /**
+         * Ledger id overflow happens on ledger manager.
+         *
+         * @since 4.5
+         */
         int LedgerIdOverflowException = -106;
 
-        // generic exception code used to propagate in replication pipeline
+        /**
+         * generic exception code used to propagate in replication pipeline
+         */
         int ReplicationException = -200;
 
-        // For all unexpected error conditions
+        /**
+         * Unexpected condition.
+         */
         int UnexpectedConditionException = -999;
     }
 
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeper.java 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeper.java
index 00f532d..e5ccba3 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeper.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeper.java
@@ -28,7 +28,6 @@ import io.netty.channel.EventLoopGroup;
 import io.netty.channel.epoll.EpollEventLoopGroup;
 import io.netty.channel.nio.NioEventLoopGroup;
 import io.netty.util.HashedWheelTimer;
-
 import java.io.IOException;
 import java.util.List;
 import java.util.Map;
@@ -39,7 +38,6 @@ import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
-
 import org.apache.bookkeeper.client.AsyncCallback.CreateCallback;
 import org.apache.bookkeeper.client.AsyncCallback.DeleteCallback;
 import org.apache.bookkeeper.client.AsyncCallback.OpenCallback;
@@ -74,16 +72,15 @@ import org.slf4j.LoggerFactory;
 
 
 /**
- * BookKeeper client. We assume there is one single writer to a ledger at any
- * time.
+ * BookKeeper client.
+ *
+ * <p>We assume there is one single writer to a ledger at any time.
  *
- * There are four possible operations: start a new ledger, write to a ledger,
+ * <p>There are four possible operations: start a new ledger, write to a 
ledger,
  * read from a ledger and delete a ledger.
  *
- * The exceptions resulting from synchronous calls and error code resulting 
from
+ * <p>The exceptions resulting from synchronous calls and error code resulting 
from
  * asynchronous calls can be found in the class {@link BKException}.
- *
- *
  */
 public class BookKeeper implements AutoCloseable {
 
@@ -148,6 +145,9 @@ public class BookKeeper implements AutoCloseable {
     boolean closed = false;
     final ReentrantReadWriteLock closeLock = new ReentrantReadWriteLock();
 
+    /**
+     * BookKeeper Client Builder to build client instances.
+     */
     public static class Builder {
         final ClientConfiguration conf;
 
@@ -162,32 +162,116 @@ public class BookKeeper implements AutoCloseable {
             this.conf = conf;
         }
 
+        /**
+         * Configure the bookkeeper client with a provided {@link 
EventLoopGroup}.
+         *
+         * @param f an external {@link EventLoopGroup} to use by the 
bookkeeper client.
+         * @return client builder.
+         * @deprecated since 4.5, use {@link #eventLoopGroup(EventLoopGroup)}
+         * @see #eventLoopGroup(EventLoopGroup)
+         */
+        @Deprecated
         public Builder setEventLoopGroup(EventLoopGroup f) {
             eventLoopGroup = f;
             return this;
         }
 
+        /**
+         * Configure the bookkeeper client with a provided {@link ZooKeeper} 
client.
+         *
+         * @param zk an external {@link ZooKeeper} client to use by the 
bookkeeper client.
+         * @return client builder.
+         * @deprecated since 4.5, use {@link #zk(ZooKeeper)}
+         * @see #zk(ZooKeeper)
+         */
+        @Deprecated
         public Builder setZookeeper(ZooKeeper zk) {
             this.zk = zk;
             return this;
         }
 
+        /**
+         * Configure the bookkeeper client with a provided {@link StatsLogger}.
+         *
+         * @param statsLogger an {@link StatsLogger} to use by the bookkeeper 
client to collect stats generated
+         *                    by the client.
+         * @return client builder.
+         * @deprecated since 4.5, use {@link #statsLogger(StatsLogger)}
+         * @see #statsLogger(StatsLogger)
+         */
+        @Deprecated
         public Builder setStatsLogger(StatsLogger statsLogger) {
             this.statsLogger = statsLogger;
             return this;
         }
 
+        /**
+         * Configure the bookkeeper client with a provided {@link 
EventLoopGroup}.
+         *
+         * @param f an external {@link EventLoopGroup} to use by the 
bookkeeper client.
+         * @return client builder.
+         * @since 4.5
+         */
+        public Builder eventLoopGroup(EventLoopGroup f) {
+            eventLoopGroup = f;
+            return this;
+        }
 
+        /**
+         * Configure the bookkeeper client with a provided {@link ZooKeeper} 
client.
+         *
+         * @param zk an external {@link ZooKeeper} client to use by the 
bookkeeper client.
+         * @return client builder.
+         * @since 4.5
+         */
+        public Builder zk(ZooKeeper zk) {
+            this.zk = zk;
+            return this;
+        }
+
+        /**
+         * Configure the bookkeeper client with a provided {@link StatsLogger}.
+         *
+         * @param statsLogger an {@link StatsLogger} to use by the bookkeeper 
client to collect stats generated
+         *                    by the client.
+         * @return client builder.
+         * @since 4.5
+         */
+        public Builder statsLogger(StatsLogger statsLogger) {
+            this.statsLogger = statsLogger;
+            return this;
+        }
+
+        /**
+         * Configure the bookkeeper client to use the provided dns resolver 
{@link DNSToSwitchMapping}.
+         *
+         * @param dnsResolver dns resolver for placement policy to use for 
resolving network locations.
+         * @return client builder
+         * @since 4.5
+         */
         public Builder dnsResolver(DNSToSwitchMapping dnsResolver) {
             this.dnsResolver = dnsResolver;
             return this;
         }
 
+        /**
+         * Configure the bookkeeper client to use a provided {@link 
HashedWheelTimer}.
+         *
+         * @param requestTimer request timer for client to manage timer 
related tasks.
+         * @return client builder
+         * @since 4.5
+         */
         public Builder requestTimer(HashedWheelTimer requestTimer) {
             this.requestTimer = requestTimer;
             return this;
         }
 
+        /**
+         * Feature Provider
+         *
+         * @param featureProvider
+         * @return
+         */
         public Builder featureProvider(FeatureProvider featureProvider) {
             this.featureProvider = featureProvider;
             return this;
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperClientStats.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperClientStats.java
index 15c6248..40d9bbc 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperClientStats.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookKeeperClientStats.java
@@ -21,6 +21,9 @@
 
 package org.apache.bookkeeper.client;
 
+/**
+ * List of constants for defining client stats names.
+ */
 public interface BookKeeperClientStats {
     public final static String CLIENT_SCOPE = "bookkeeper_client";
 
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookieInfoReader.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookieInfoReader.java
index da66848..484e54b 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookieInfoReader.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookieInfoReader.java
@@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicInteger;
 
+import org.apache.bookkeeper.common.annotation.InterfaceAudience;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.bookkeeper.client.WeightedRandomSelection.WeightedObject;
 import org.apache.bookkeeper.conf.ClientConfiguration;
@@ -38,6 +39,11 @@ import org.apache.bookkeeper.proto.BookkeeperProtocol;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * A utility class to read {@link BookieInfo} from bookies.
+ *
+ * <p>NOTE: This class is tended to be used by this project only. External 
users should not rely on it directly.
+ */
 public class BookieInfoReader {
     private static final Logger LOG = 
LoggerFactory.getLogger(BookieInfoReader.class);
     private static final long GET_BOOKIE_INFO_REQUEST_FLAGS
@@ -55,6 +61,11 @@ public class BookieInfoReader {
     private final AtomicBoolean isQueued = new AtomicBoolean();
     private final AtomicBoolean refreshBookieList = new AtomicBoolean();
 
+    /**
+     * A class represents the information (e.g. disk usage, load) of a bookie.
+     *
+     * <p>NOTE: This class is tended to be used by this project only. External 
users should not rely on it directly.
+     */
     public static class BookieInfo implements WeightedObject {
         private final long freeDiskSpace;
         private final long totalDiskSpace;
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookiesListener.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookiesListener.java
index 2f125fb..0a1a884 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookiesListener.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookiesListener.java
@@ -1,5 +1,3 @@
-package org.apache.bookkeeper.client;
-
 /**
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -17,11 +15,21 @@ package org.apache.bookkeeper.client;
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.bookkeeper.client;
 
+import org.apache.bookkeeper.common.annotation.InterfaceAudience;
+import org.apache.bookkeeper.common.annotation.InterfaceStability;
 
 /**
  * Listener for the the available bookies changes.
  */
+
[email protected]
[email protected]
 public interface BookiesListener {
+
+    /**
+     * Callback method triggered when the list of available bookies are 
changed.
+     */
     void availableBookiesChanged();
 }
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/DefaultEnsemblePlacementPolicy.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/DefaultEnsemblePlacementPolicy.java
index 24b1c8e..d401233 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/DefaultEnsemblePlacementPolicy.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/DefaultEnsemblePlacementPolicy.java
@@ -40,7 +40,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Default Ensemble Placement Policy, which picks bookies randomly
+ * Default Ensemble Placement Policy, which picks bookies randomly.
+ *
+ * @see EnsemblePlacementPolicy
  */
 public class DefaultEnsemblePlacementPolicy implements EnsemblePlacementPolicy 
{
     static final Logger LOG = 
LoggerFactory.getLogger(DefaultEnsemblePlacementPolicy.class);
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/DefaultSpeculativeRequestExecutionPolicy.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/DefaultSpeculativeRequestExecutionPolicy.java
index 614f68e..3c3daba 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/DefaultSpeculativeRequestExecutionPolicy.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/DefaultSpeculativeRequestExecutionPolicy.java
@@ -31,6 +31,12 @@ import com.google.common.util.concurrent.ListenableFuture;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * A default implementation of {@link SpeculativeRequestExecutionPolicy}.
+ *
+ * <p>The policy issues speculative requests in a backoff way. The time 
between two speculative requests
+ * are between {@code firstSpeculativeRequestTimeout} and {@code 
maxSpeculativeRequestTimeout}.
+ */
 public class DefaultSpeculativeRequestExecutionPolicy implements 
SpeculativeRequestExecutionPolicy {
     private static final Logger LOG = 
LoggerFactory.getLogger(PendingReadOp.class);
     final int firstSpeculativeRequestTimeout;
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/EnsemblePlacementPolicy.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/EnsemblePlacementPolicy.java
index 0561386..8a9b86a 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/EnsemblePlacementPolicy.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/EnsemblePlacementPolicy.java
@@ -17,18 +17,17 @@
  */
 package org.apache.bookkeeper.client;
 
+import io.netty.util.HashedWheelTimer;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
-
-
-import io.netty.util.HashedWheelTimer;
 import java.util.Optional;
-
+import java.util.Set;
 import org.apache.bookkeeper.client.BKException.BKNotEnoughBookiesException;
 import org.apache.bookkeeper.client.BookieInfoReader.BookieInfo;
+import org.apache.bookkeeper.common.annotation.InterfaceAudience;
+import org.apache.bookkeeper.common.annotation.InterfaceStability;
 import org.apache.bookkeeper.conf.ClientConfiguration;
 import org.apache.bookkeeper.feature.FeatureProvider;
 import org.apache.bookkeeper.net.BookieSocketAddress;
@@ -36,9 +35,164 @@ import org.apache.bookkeeper.net.DNSToSwitchMapping;
 import org.apache.bookkeeper.stats.StatsLogger;
 
 /**
- * Encapsulation of the algorithm that selects a number of bookies from the 
cluster as an ensemble for storing
- * data, based on the data input as well as the node properties.
+ * {@link EnsemblePlacementPolicy} encapsulates the algorithm that bookkeeper 
client uses to select a number of bookies
+ * from the cluster as an ensemble for storing entries.
+ *
+ * <p>The algorithm is typically implemented based on the data input as well 
as the network topology properties.
+ *
+ * <h2>How does it work?</h2>
+ *
+ * This interface basically covers three parts:
+ * <p><ul>
+ * <li>Initialization and uninitialization</li>
+ * <li>How to choose bookies to place data</li>
+ * <li>How to choose bookies to do speculative reads</li>
+ * </ul></p>
+ *
+ * <h3>Initialization and uninitialization</h3>
+ *
+ * <p>The ensemble placement policy is constructed by jvm reflection during 
constructing bookkeeper client.
+ * After the {@code EnsemblePlacementPolicy} is constructed, bookkeeper client 
will call
+ * {@link #initialize(ClientConfiguration, Optional, HashedWheelTimer, 
FeatureProvider, StatsLogger)} to initialize
+ * the placement policy.
+ *
+ * <p>The {@link #initialize(ClientConfiguration, Optional, HashedWheelTimer, 
FeatureProvider, StatsLogger)}
+ * method takes a few resources from bookkeeper for instantiating itself. 
These resources include:
+ *
+ * <p><ul>
+ * <li>`ClientConfiguration` : The client configuration that used for 
constructing the bookkeeper client.
+ *                             The implementation of the placement policy 
could obtain its settings from this
+ *                             configuration.
+ * <li>`DNSToSwitchMapping`: The DNS resolver for the ensemble policy to build 
the network topology of the bookies
+ *                           cluster. It is optional.
+ * <li>`HashedWheelTimer`: A hashed wheel timer that could be used for timing 
related work.
+ *                         For example, a stabilize network topology could use 
it to delay network topology changes to
+ *                         reduce impacts of flapping bookie registrations due 
to zk session expires.
+ * <li>`FeatureProvider`: A {@link FeatureProvider} that the policy could use 
for enabling or disabling its offered
+ *                        features. For example, a {@link 
RegionAwareEnsemblePlacementPolicy} could offer features
+ *                        to disable placing data to a specific region at 
runtime.
+ * <li>`StatsLogger`: A {@link StatsLogger} for exposing stats.
+ * </ul></p>
+ *
+ * <p>The ensemble placement policy is a single instance per bookkeeper 
client. The instance will
+ * be {@link #uninitalize()} when closing the bookkeeper client. The 
implementation of a placement policy should be
+ * responsible for releasing all the resources that allocated during
+ * {@link #initialize(ClientConfiguration, Optional, HashedWheelTimer, 
FeatureProvider, StatsLogger)}.
+ *
+ * <h3>How to choose bookies to place data</h3>
+ *
+ * <p>The bookkeeper client discovers list of bookies from zookeeper via 
{@code BookieWatcher} - whenever there are
+ * bookie changes, the ensemble placement policy will be notified with new 
list of bookies via
+ * {@link #onClusterChanged(Set, Set)}. The implementation of the ensemble 
placement policy will react on those
+ * changes to build new network topology. Subsequent operations like {@link 
#newEnsemble(int, int, int, Map, Set)} or
+ * {@link #replaceBookie(int, int, int, Map, Collection, BookieSocketAddress, 
Set)} hence can operate on the new
+ * network topology.
+ *
+ * <p>Both {@link RackawareEnsemblePlacementPolicy} and {@link 
RegionAwareEnsemblePlacementPolicy} are
+ * {@link TopologyAwareEnsemblePlacementPolicy}s. They build a {@link 
org.apache.bookkeeper.net.NetworkTopology} on
+ * bookie changes, use it for ensemble placement and ensure {@code 
rack/region} coverage for write quorums.
+ *
+ * <h4>Network Topology</h4>
+ *
+ * <p>The network topology is presenting a cluster of bookies in a tree 
hierarchical structure. For example,
+ * a bookie cluster may be consists of many data centers (aka regions) filled 
with racks of machines.
+ * In this tree structure, leaves represent bookies and inner nodes represent 
switches/routes that manage
+ * traffic in/out of regions or racks.
+ *
+ * <p>For example, there are 3 bookies in region `A`. They are `bk1`, `bk2` 
and `bk3`. And their network locations are
+ * {@code /region-a/rack-1/bk1}, {@code /region-a/rack-1/bk2} and {@code 
/region-a/rack-2/bk3}. So the network topology
+ * will look like below:
+ *
+ * <pre>
+ *      root
+ *        |
+ *     region-a
+ *       /  \
+ * rack-1  rack-2
+ *   /  \       \
+ * bk1  bk2     bk3
+ * </pre>
+ *
+ * <p>Another example, there are 4 bookies spanning in two regions `A` and 
`B`. They are `bk1`, `bk2`, `bk3` and `bk4`.
+ * And their network locations are {@code /region-a/rack-1/bk1}, {@code 
/region-a/rack-1/bk2},
+ * {@code /region-b/rack-2/bk3} and {@code /region-b/rack-2/bk4}. The network 
topology will look like below:
+ *
+ * <pre>
+ *         root
+ *         /  \
+ * region-a  region-b
+ *     |         |
+ *   rack-1    rack-2
+ *     / \       / \
+ *   bk1  bk2  bk3  bk4
+ * </pre>
+ *
+ * <p> The network location of each bookie is resolved by a {@link 
DNSToSwitchMapping}. The {@link DNSToSwitchMapping}
+ * resolves a list of DNS-names or IP-addresses into a list of network 
locations. The network location that is returned
+ * must be a network path of the form `/region/rack`, where `/` is the root, 
and `region` is the region id representing
+ * the data center where `rack` is located. The network topology of the bookie 
cluster would determine the number of
+ *
+ * <h4>RackAware and RegionAware</h4>
+ *
+ * <p>{@link RackawareEnsemblePlacementPolicy} basically just chooses bookies 
from different racks in the built
+ * network topology. It guarantees that a write quorum will cover at least two 
racks. It expects the network locations
+ * resolved by {@link DNSToSwitchMapping} have at least 2 levels. For example, 
network location paths like
+ * {@code /dc1/rack0} and {@code /dc1/row1/rack0} are okay, but {@link /rack0} 
is not acceptable.
+ *
+ * <p>{@link RegionAwareEnsemblePlacementPolicy} is a hierarchical placement 
policy, which it chooses
+ * equal-sized bookies from regions, and within each region it uses {@link 
RackawareEnsemblePlacementPolicy} to choose
+ * bookies from racks. For example, if there is 3 regions - {@code region-a}, 
{@code region-b} and {@code region-c},
+ * an application want to allocate a {@code 15-bookies} ensemble. First, it 
would figure out there are 3 regions and
+ * it should allocate 5 bookies from each region. Second, for each region, it 
would use
+ * {@link RackawareEnsemblePlacementPolicy} to choose <i>5</i> bookies.
+ *
+ * <p>Since {@link RegionAwareEnsemblePlacementPolicy} is based on {@link 
RackawareEnsemblePlacementPolicy}, it expects
+ * the network locations resolved by {@link DNSToSwitchMapping} have at least 
<b>3</b> levels.
+ *
+ * <h3>How to choose bookies to do speculative reads?</h3>
+ *
+ * <p>{@link #reorderReadSequence(ArrayList, List, Map)} and {@link 
#reorderReadLACSequence(ArrayList, List, Map)} are
+ * two methods exposed by the placement policy, to help client determine a 
better read sequence according to the
+ * network topology and the bookie failure history.
+ *
+ * <p>For example, in {@link RackawareEnsemblePlacementPolicy}, the reads will 
be attempted in following sequence:
+ *
+ * <p><ul>
+ * <li>bookies are writable and didn't experience failures before
+ * <li>bookies are writable and experienced failures before
+ * <li>bookies are readonly
+ * <li>bookies already disappeared from network topology
+ * </ul></p>
+ *
+ * <p>In {@link RegionAwareEnsemblePlacementPolicy}, the reads will be tried 
in similar following sequence
+ * as `RackAware` placement policy. There is a slight different on trying 
writable bookies: after trying every 2
+ * bookies from local region, it would try a bookie from remote region. Hence 
it would achieve low latency even
+ * there is network issues within local region.
+ *
+ * <h2>How to configure the placement policy?</h2>
+ *
+ * <p>Currently there are 3 implementations available by default. They are:
+ * <ul>
+ *     <li>{@link DefaultEnsemblePlacementPolicy}</li>
+ *     <li>{@link RackawareEnsemblePlacementPolicy}</li>
+ *     <li>{@link RegionAwareEnsemblePlacementPolicy}</li>
+ * </ul>
+ *
+ * <p>You can configure the ensemble policy by specifying the placement policy 
class in
+ * {@link ClientConfiguration#setEnsemblePlacementPolicy(Class)}.
+ *
+ * <p>{@link DefaultEnsemblePlacementPolicy} randomly pickups bookies from the 
cluster, while both
+ * {@link RackawareEnsemblePlacementPolicy} and {@link 
RegionAwareEnsemblePlacementPolicy} choose bookies based on
+ * network locations. So you might also consider configuring a proper {@link 
DNSToSwitchMapping} in
+ * {@link BookKeeper.Builder} to resolve the correct network locations for 
your cluster.
+ *
+ * @see TopologyAwareEnsemblePlacementPolicy
+ * @see DefaultEnsemblePlacementPolicy
+ * @see RackawareEnsemblePlacementPolicy
+ * @see RegionAwareEnsemblePlacementPolicy
  */
[email protected]
[email protected]
 public interface EnsemblePlacementPolicy {
 
     /**
@@ -49,6 +203,8 @@ public interface EnsemblePlacementPolicy {
      * @param hashedWheelTimer timer
      * @param featureProvider feature provider
      * @param statsLogger stats logger
+     *
+     * @since 4.5
      */
     public EnsemblePlacementPolicy initialize(ClientConfiguration conf,
                                               Optional<DNSToSwitchMapping> 
optionalDnsResolver,
@@ -65,6 +221,10 @@ public interface EnsemblePlacementPolicy {
      * A consistent view of the cluster (what bookies are available as 
writable, what bookies are available as
      * readonly) is updated when any changes happen in the cluster.
      *
+     * <p>The implementation should take actions when the cluster view is 
changed. So subsequent
+     * {@link #newEnsemble(int, int, int, Map, Set)} and
+     * {@link #replaceBookie(int, int, int, Map, Collection, 
BookieSocketAddress, Set)} can choose proper bookies.
+     *
      * @param writableBookies
      *          All the bookies in the cluster available for write/read.
      * @param readOnlyBookies
@@ -78,18 +238,30 @@ public interface EnsemblePlacementPolicy {
      * Choose <i>numBookies</i> bookies for ensemble. If the count is more 
than the number of available
      * nodes, {@link BKNotEnoughBookiesException} is thrown.
      *
+     * <p>The implementation should respect to the replace settings. The size 
of the returned bookie list
+     * should be equal to the provide {@code ensembleSize}.
+     *
+     * <p>{@code customMetadata} is the same user defined data that user 
provides
+     * when {@link BookKeeper#createLedger(int, int, int, 
BookKeeper.DigestType, byte[], Map)}.
+     *
      * @param ensembleSize
      *          Ensemble Size
      * @param writeQuorumSize
      *          Write Quorum Size
      * @param ackQuorumSize
-     *          the value of ackQuorumSize
-     * @param customMetadata the value of customMetadata
+     *          the value of ackQuorumSize (added since 4.5)
+     * @param customMetadata the value of customMetadata. it is the same user 
defined metadata that user
+     *                       provides in {@link BookKeeper#createLedger(int, 
int, int, BookKeeper.DigestType, byte[])}
      * @param excludeBookies Bookies that should not be considered as targets.
      * @throws BKNotEnoughBookiesException if not enough bookies available.
      * @return the 
java.util.ArrayList<org.apache.bookkeeper.net.BookieSocketAddress>
      */
-    public ArrayList<BookieSocketAddress> newEnsemble(int ensembleSize, int 
writeQuorumSize, int ackQuorumSize, Map<String, byte[]> customMetadata, 
Set<BookieSocketAddress> excludeBookies) throws BKNotEnoughBookiesException;
+    public ArrayList<BookieSocketAddress> newEnsemble(int ensembleSize,
+                                                      int writeQuorumSize,
+                                                      int ackQuorumSize,
+                                                      Map<String, byte[]> 
customMetadata,
+                                                      Set<BookieSocketAddress> 
excludeBookies)
+        throws BKNotEnoughBookiesException;
 
     /**
      * Choose a new bookie to replace <i>bookieToReplace</i>. If no bookie 
available in the cluster,
@@ -99,15 +271,23 @@ public interface EnsemblePlacementPolicy {
      *          the value of ensembleSize
      * @param writeQuorumSize
      *          the value of writeQuorumSize
-     * @param ackQuorumSize the value of ackQuorumSize
-     * @param customMetadata the value of customMetadata
+     * @param ackQuorumSize the value of ackQuorumSize (added since 4.5)
+     * @param customMetadata the value of customMetadata. it is the same user 
defined metadata that user
+     *                       provides in {@link BookKeeper#createLedger(int, 
int, int, BookKeeper.DigestType, byte[])}
      * @param currentEnsemble the value of currentEnsemble
      * @param bookieToReplace bookie to replace
      * @param excludeBookies bookies that should not be considered as 
candidate.
      * @throws BKNotEnoughBookiesException
      * @return the org.apache.bookkeeper.net.BookieSocketAddress
      */
-    public BookieSocketAddress replaceBookie(int ensembleSize, int 
writeQuorumSize, int ackQuorumSize, java.util.Map<String, byte[]> 
customMetadata, Collection<BookieSocketAddress> currentEnsemble, 
BookieSocketAddress bookieToReplace, Set<BookieSocketAddress> excludeBookies) 
throws BKNotEnoughBookiesException;
+    public BookieSocketAddress replaceBookie(int ensembleSize,
+                                             int writeQuorumSize,
+                                             int ackQuorumSize,
+                                             Map<String, byte[]> 
customMetadata,
+                                             Collection<BookieSocketAddress> 
currentEnsemble,
+                                             BookieSocketAddress 
bookieToReplace,
+                                             Set<BookieSocketAddress> 
excludeBookies)
+        throws BKNotEnoughBookiesException;
 
     /**
      * Reorder the read sequence of a given write quorum <i>writeSet</i>.
@@ -119,9 +299,11 @@ public interface EnsemblePlacementPolicy {
      * @param bookieFailureHistory
      *          Observed failures on the bookies
      * @return read sequence of bookies
+     * @since 4.5
      */
     public List<Integer> reorderReadSequence(ArrayList<BookieSocketAddress> 
ensemble,
-                                             List<Integer> writeSet, 
Map<BookieSocketAddress, Long> bookieFailureHistory);
+                                             List<Integer> writeSet,
+                                             Map<BookieSocketAddress, Long> 
bookieFailureHistory);
 
 
     /**
@@ -134,15 +316,18 @@ public interface EnsemblePlacementPolicy {
      * @param bookieFailureHistory
      *          Observed failures on the bookies
      * @return read sequence of bookies
+     * @since 4.5
      */
     public List<Integer> reorderReadLACSequence(ArrayList<BookieSocketAddress> 
ensemble,
-                                                List<Integer> writeSet, 
Map<BookieSocketAddress, Long> bookieFailureHistory);
+                                                List<Integer> writeSet,
+                                                Map<BookieSocketAddress, Long> 
bookieFailureHistory);
 
     /**
      * Send the bookie info details.
      * 
      * @param bookieInfoMap
      *          A map that has the bookie to BookieInfo
+     * @since 4.5
      */
     default public void updateBookieInfo(Map<BookieSocketAddress, BookieInfo> 
bookieInfoMap) {
     }
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/ITopologyAwareEnsemblePlacementPolicy.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/ITopologyAwareEnsemblePlacementPolicy.java
index 535fffe..2828f0b 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/ITopologyAwareEnsemblePlacementPolicy.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/ITopologyAwareEnsemblePlacementPolicy.java
@@ -17,6 +17,8 @@
  */
 package org.apache.bookkeeper.client;
 
+import org.apache.bookkeeper.common.annotation.InterfaceAudience;
+import org.apache.bookkeeper.common.annotation.InterfaceStability;
 import org.apache.bookkeeper.net.BookieSocketAddress;
 import org.apache.bookkeeper.net.Node;
 
@@ -25,19 +27,26 @@ import java.util.Set;
 
 /**
  * Interface for topology aware ensemble placement policy.
+ *
+ * <p>All the implementations of this interface are using {@link 
org.apache.bookkeeper.net.NetworkTopology}
+ *    for placing ensembles.
+ *
+ * @see EnsemblePlacementPolicy
  */
[email protected]
[email protected]
 public interface ITopologyAwareEnsemblePlacementPolicy<T extends Node> extends 
EnsemblePlacementPolicy {
     /**
      * Predicate used when choosing an ensemble.
      */
-    public static interface Predicate<T extends Node> {
+    static interface Predicate<T extends Node> {
         boolean apply(T candidate, Ensemble<T> chosenBookies);
     }
 
     /**
      * Ensemble used to hold the result of an ensemble selected for placement.
      */
-    public static interface Ensemble<T extends Node> {
+    static interface Ensemble<T extends Node> {
 
         /**
          * Append the new bookie node to the ensemble only if the ensemble 
doesnt
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerChecker.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerChecker.java
index 7f58131..c9481bd 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerChecker.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerChecker.java
@@ -37,7 +37,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- *Checks the complete ledger and finds the UnderReplicated fragments if any
+ * A utility class to check the complete ledger and finds the UnderReplicated 
fragments if any.
+ *
+ * <p>NOTE: This class is tended to be used by this project only. External 
users should not rely on it directly.
  */
 public class LedgerChecker {
     private final static Logger LOG = 
LoggerFactory.getLogger(LedgerChecker.class);
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerMetadata.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerMetadata.java
index 92fc63e..55e3987 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerMetadata.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/LedgerMetadata.java
@@ -46,8 +46,9 @@ import com.google.common.collect.Maps;
 
 /**
  * This class encapsulates all the ledger metadata that is persistently stored
- * in zookeeper. It provides parsing and serialization methods of such 
metadata.
+ * in metadata store.
  *
+ * <p>It provides parsing and serialization methods of such metadata.
  */
 public class LedgerMetadata {
     static final Logger LOG = LoggerFactory.getLogger(LedgerMetadata.class);
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/MacDigestManager.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/MacDigestManager.java
index fc526aa..62faf82 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/MacDigestManager.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/MacDigestManager.java
@@ -21,18 +21,20 @@ package org.apache.bookkeeper.client;
 import static com.google.common.base.Charsets.UTF_8;
 
 import io.netty.buffer.ByteBuf;
-
 import java.security.GeneralSecurityException;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
 import java.util.Arrays;
-
 import javax.crypto.Mac;
 import javax.crypto.spec.SecretKeySpec;
-
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * A {@code SHA-1} based digest manager.
+ *
+ * <p>NOTE: This class is tended to be used by this project only. External 
users should not rely on it directly.
+ */
 public class MacDigestManager extends DigestManager {
     private final static Logger LOG = 
LoggerFactory.getLogger(MacDigestManager.class);
 
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/RackawareEnsemblePlacementPolicy.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/RackawareEnsemblePlacementPolicy.java
index a72e2ca..0eb8b92 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/RackawareEnsemblePlacementPolicy.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/RackawareEnsemblePlacementPolicy.java
@@ -29,6 +29,11 @@ import org.apache.bookkeeper.stats.StatsLogger;
 
 import io.netty.util.HashedWheelTimer;
 
+/**
+ * A placement policy implementation use rack information for placing 
ensembles.
+ *
+ * @see EnsemblePlacementPolicy
+ */
 public class RackawareEnsemblePlacementPolicy extends 
RackawareEnsemblePlacementPolicyImpl
         implements 
ITopologyAwareEnsemblePlacementPolicy<TopologyAwareEnsemblePlacementPolicy.BookieNode>
 {
     RackawareEnsemblePlacementPolicyImpl slave = null;
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/ReadLastConfirmedAndEntryOp.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/ReadLastConfirmedAndEntryOp.java
index d2de714..ca067d4 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/ReadLastConfirmedAndEntryOp.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/ReadLastConfirmedAndEntryOp.java
@@ -20,6 +20,7 @@
  */
 package org.apache.bookkeeper.client;
 
+import com.google.common.util.concurrent.ListenableFuture;
 import io.netty.buffer.ByteBuf;
 import java.util.ArrayList;
 import java.util.BitSet;
@@ -28,18 +29,20 @@ import java.util.concurrent.Callable;
 import java.util.concurrent.ScheduledExecutorService;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicBoolean;
-
-import com.google.common.base.Optional;
-import com.google.common.util.concurrent.ListenableFuture;
-
 import org.apache.bookkeeper.net.BookieSocketAddress;
 import org.apache.bookkeeper.proto.BookieProtocol;
 import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks;
+import org.apache.bookkeeper.proto.ReadLastConfirmedAndEntryContext;
 import org.apache.bookkeeper.util.MathUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class ReadLastConfirmedAndEntryOp implements 
BookkeeperInternalCallbacks.ReadEntryCallback, SpeculativeRequestExecutor {
+/**
+ * Long poll read operation.
+ */
+class ReadLastConfirmedAndEntryOp implements 
BookkeeperInternalCallbacks.ReadEntryCallback,
+                                             SpeculativeRequestExecutor {
+
     static final Logger LOG = 
LoggerFactory.getLogger(ReadLastConfirmedAndEntryOp.class);
 
     final private ScheduledExecutorService scheduler;
@@ -485,38 +488,6 @@ public class ReadLastConfirmedAndEntryOp implements 
BookkeeperInternalCallbacks.
         public void readLastConfirmedAndEntryComplete(int rc, long 
lastAddConfirmed, LedgerEntry entry);
     }
 
-    public static class ReadLastConfirmedAndEntryContext implements 
BookkeeperInternalCallbacks.ReadEntryCallbackCtx {
-        final int bookieIndex;
-        final BookieSocketAddress bookie;
-        long lac = LedgerHandle.INVALID_ENTRY_ID;
-        Optional<Long> lacUpdateTimestamp = Optional.absent();
-
-        ReadLastConfirmedAndEntryContext(int bookieIndex, BookieSocketAddress 
bookie) {
-            this.bookieIndex = bookieIndex;
-            this.bookie = bookie;
-        }
-
-        @Override
-        public void setLastAddConfirmed(long lac) {
-            this.lac = lac;
-        }
-
-        @Override
-        public long getLastAddConfirmed() {
-            return lac;
-        }
-
-        public Optional<Long> getLacUpdateTimestamp() {
-            return lacUpdateTimestamp;
-        }
-
-        public void setLacUpdateTimestamp(long lacUpdateTimestamp) {
-            this.lacUpdateTimestamp = Optional.of(lacUpdateTimestamp);
-        }
-
-
-    }
-
     private void submitCallback(int rc, long lastAddConfirmed, LedgerEntry 
entry) {
         long latencyMicros = MathUtils.elapsedMicroSec(requestTimeNano);
         if (BKException.Code.OK != rc) {
@@ -536,7 +507,7 @@ public class ReadLastConfirmedAndEntryOp implements 
BookkeeperInternalCallbacks.
                 new Object[] { getClass().getName(), ledgerId, entryId, rc });
         }
         ReadLastConfirmedAndEntryContext rCtx = 
(ReadLastConfirmedAndEntryContext) ctx;
-        BookieSocketAddress bookie = rCtx.bookie;
+        BookieSocketAddress bookie = rCtx.getBookieAddress();
         numResponsesPending--;
         if (BKException.Code.OK == rc) {
             if (LOG.isTraceEnabled()) {
@@ -552,7 +523,7 @@ public class ReadLastConfirmedAndEntryOp implements 
BookkeeperInternalCallbacks.
             hasValidResponse = true;
 
             if (entryId != BookieProtocol.LAST_ADD_CONFIRMED) {
-                if (request.complete(rCtx.bookieIndex, bookie, buffer, 
entryId)) {
+                if (request.complete(rCtx.getBookieIndex(), bookie, buffer, 
entryId)) {
                     // callback immediately
                     if (rCtx.getLacUpdateTimestamp().isPresent()) {
                         long elapsedMicros = 
TimeUnit.MILLISECONDS.toMicros(System.currentTimeMillis() - 
rCtx.getLacUpdateTimestamp().get());
@@ -563,10 +534,10 @@ public class ReadLastConfirmedAndEntryOp implements 
BookkeeperInternalCallbacks.
 
                     submitCallback(BKException.Code.OK, lastAddConfirmed, 
request);
                     requestComplete.set(true);
-                    heardFromHostsBitSet.set(rCtx.bookieIndex, true);
+                    heardFromHostsBitSet.set(rCtx.getBookieIndex(), true);
                 }
             } else {
-                emptyResponsesFromHostsBitSet.set(rCtx.bookieIndex, true);
+                emptyResponsesFromHostsBitSet.set(rCtx.getBookieIndex(), true);
                 if (lastAddConfirmed > prevEntryId) {
                     // received advanced lac
                     completeRequest();
@@ -580,10 +551,10 @@ public class ReadLastConfirmedAndEntryOp implements 
BookkeeperInternalCallbacks.
                     if (LOG.isDebugEnabled()) {
                         LOG.debug("Received empty response for 
readLACAndEntry(lid = {}, previousEntryId = {}) from" +
                                         " bookie {} @ {}, reattempting reading 
next bookie : lac = {}",
-                                new Object[]{ledgerId, prevEntryId, 
rCtx.bookieIndex,
-                                        rCtx.bookie, lastAddConfirmed});
+                                new Object[]{ledgerId, prevEntryId, 
rCtx.getBookieAddress(),
+                                        rCtx.getBookieAddress(), 
lastAddConfirmed});
                     }
-                    request.logErrorAndReattemptRead(rCtx.bookieIndex, bookie, 
"Empty Response", rc);
+                    request.logErrorAndReattemptRead(rCtx.getBookieIndex(), 
bookie, "Empty Response", rc);
                 }
                 return;
             }
@@ -591,7 +562,7 @@ public class ReadLastConfirmedAndEntryOp implements 
BookkeeperInternalCallbacks.
             submitCallback(rc, lastAddConfirmed, null);
             requestComplete.set(true);
         } else {
-            request.logErrorAndReattemptRead(rCtx.bookieIndex, bookie, "Error: 
" + BKException.getMessage(rc), rc);
+            request.logErrorAndReattemptRead(rCtx.getBookieIndex(), bookie, 
"Error: " + BKException.getMessage(rc), rc);
             return;
         }
 
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/RegionAwareEnsemblePlacementPolicy.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/RegionAwareEnsemblePlacementPolicy.java
index c7f2802..89415a1 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/RegionAwareEnsemblePlacementPolicy.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/RegionAwareEnsemblePlacementPolicy.java
@@ -43,6 +43,11 @@ import org.apache.commons.lang3.tuple.Pair;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+/**
+ * A placement policy use region information in the network topology for 
placing ensembles.
+ *
+ * @see EnsemblePlacementPolicy
+ */
 public class RegionAwareEnsemblePlacementPolicy extends 
RackawareEnsemblePlacementPolicy {
     static final Logger LOG = 
LoggerFactory.getLogger(RegionAwareEnsemblePlacementPolicy.class);
 
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/SpeculativeRequestExecutionPolicy.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/SpeculativeRequestExecutionPolicy.java
index a55bf6f..787f2a0 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/SpeculativeRequestExecutionPolicy.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/SpeculativeRequestExecutionPolicy.java
@@ -22,6 +22,14 @@ package org.apache.bookkeeper.client;
 
 import java.util.concurrent.ScheduledExecutorService;
 
+/**
+ * Define a policy for speculative request execution. 
+ *
+ * <p>The implementation can define its execution policy. For example, when to 
issue speculative requests
+ * and how many speculative requests to issue.
+ *
+ * @since 4.5
+ */
 public interface SpeculativeRequestExecutionPolicy {
 
     /**
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/SpeculativeRequestExecutor.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/SpeculativeRequestExecutor.java
index 450cdb3..0d7039b 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/SpeculativeRequestExecutor.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/SpeculativeRequestExecutor.java
@@ -22,6 +22,14 @@ package org.apache.bookkeeper.client;
 
 import com.google.common.util.concurrent.ListenableFuture;
 
+/**
+ * Define an executor for issuing speculative requests.
+ *
+ * <p>If the implementation can issue a speculative read, it should return true
+ * to indicate a speculative request should be issued. Otherwise, return false.
+ *
+ * @since 4.5
+ */
 public interface SpeculativeRequestExecutor {
 
     /**
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/SynchCallbackUtils.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/SynchCallbackUtils.java
index bc982b9..656c6d9 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/SynchCallbackUtils.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/SynchCallbackUtils.java
@@ -24,7 +24,7 @@ import java.util.concurrent.ExecutionException;
  * Utility for callbacks
  * 
  */
-public class SynchCallbackUtils {
+class SynchCallbackUtils {
 
     /**
      * Wait for a result. This is convenience method to implement callbacks
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/WeightedRandomSelection.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/WeightedRandomSelection.java
index f185e11..38a03b0 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/WeightedRandomSelection.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/WeightedRandomSelection.java
@@ -31,7 +31,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class WeightedRandomSelection<T> {
+class WeightedRandomSelection<T> {
     static final Logger LOG = 
LoggerFactory.getLogger(WeightedRandomSelection.class);
 
     interface WeightedObject {
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/ClientConnectionPeer.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/package-info.java
similarity index 78%
copy from 
bookkeeper-server/src/main/java/org/apache/bookkeeper/client/ClientConnectionPeer.java
copy to 
bookkeeper-server/src/main/java/org/apache/bookkeeper/client/package-info.java
index 322cba9..e52a7d1 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/ClientConnectionPeer.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/package-info.java
@@ -1,4 +1,4 @@
-/**
+/*
  *
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
@@ -18,13 +18,7 @@
  * under the License.
  *
  */
-package org.apache.bookkeeper.client;
-
-import org.apache.bookkeeper.proto.ConnectionPeer;
-
 /**
- * Represents the connection to a Bookie, from the client side
+ * BookKeeper Client.
  */
-public interface ClientConnectionPeer extends ConnectionPeer {
-
-}
+package org.apache.bookkeeper.client;
\ No newline at end of file
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/common/annotation/InterfaceAudience.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/common/annotation/InterfaceAudience.java
new file mode 100644
index 0000000..40fcef6
--- /dev/null
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/common/annotation/InterfaceAudience.java
@@ -0,0 +1,56 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.bookkeeper.common.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Annotation to inform users of a package, class or method's intended 
audience.
+ */
[email protected]
[email protected]
+public class InterfaceAudience {
+
+    /**
+     * Intended for use by any project or application.
+     */
+    @Documented
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface Public {};
+
+    /**
+     * Intended for use only within the project(s) specified in the annotation.
+     * For example, "distributedlog", "pulsar".
+     */
+    @Documented
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface LimitedPrivate {};
+
+    /**
+     * Intended for use only within bookkeeper itself.
+     */
+    @Documented
+    @Retention(RetentionPolicy.RUNTIME)
+    public @interface Private {};
+
+    private InterfaceAudience() {} // Audience can't exist on its own
+
+}
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/common/annotation/InterfaceStability.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/common/annotation/InterfaceStability.java
new file mode 100644
index 0000000..174afd5
--- /dev/null
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/common/annotation/InterfaceStability.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.bookkeeper.common.annotation;
+
+import java.lang.annotation.Documented;
+
+/**
+ * Annotation to inform users of how much to rely on a particular package,
+ * class or method not changing over time.
+ */
[email protected]
[email protected]
+public class InterfaceStability {
+  /**
+   * Can evolve while retaining compatibility for minor release boundaries.;
+   * can break compatibility only at major release (ie. at m.0).
+   */
+  @Documented
+  public @interface Stable {};
+
+  /**
+   * Evolving, but can break compatibility at minor release (i.e. m.x)
+   */
+  @Documented
+  public @interface Evolving {};
+
+  /**
+   * No guarantee is provided as to reliability or stability across any
+   * level of release granularity.
+   */
+  @Documented
+  public @interface Unstable {};
+
+  private InterfaceStability() {}
+}
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookiesListener.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/common/annotation/package-info.java
similarity index 77%
copy from 
bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookiesListener.java
copy to 
bookkeeper-server/src/main/java/org/apache/bookkeeper/common/annotation/package-info.java
index 2f125fb..b0fe537 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookiesListener.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/common/annotation/package-info.java
@@ -1,6 +1,4 @@
-package org.apache.bookkeeper.client;
-
-/**
+/*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -9,7 +7,7 @@ package org.apache.bookkeeper.client;
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,10 +16,7 @@ package org.apache.bookkeeper.client;
  * limitations under the License.
  */
 
-
 /**
- * Listener for the the available bookies changes.
+ * Annotations used across the whole project.
  */
-public interface BookiesListener {
-    void availableBookiesChanged();
-}
+package org.apache.bookkeeper.common.annotation;
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookiesListener.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/common/package-info.java
similarity index 77%
copy from 
bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookiesListener.java
copy to 
bookkeeper-server/src/main/java/org/apache/bookkeeper/common/package-info.java
index 2f125fb..23e9ae6 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/BookiesListener.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/common/package-info.java
@@ -1,6 +1,4 @@
-package org.apache.bookkeeper.client;
-
-/**
+/*
  * Licensed to the Apache Software Foundation (ASF) under one
  * or more contributor license agreements.  See the NOTICE file
  * distributed with this work for additional information
@@ -9,7 +7,7 @@ package org.apache.bookkeeper.client;
  * "License"); you may not use this file except in compliance
  * with the License.  You may obtain a copy of the License at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *      http://www.apache.org/licenses/LICENSE-2.0
  *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
@@ -18,10 +16,9 @@ package org.apache.bookkeeper.client;
  * limitations under the License.
  */
 
-
 /**
- * Listener for the the available bookies changes.
+ * Common functions and utils used across the project.
+ *
+ * <p>NOTE: refactor this package to bookkeeper-common module after 4.5</p>
  */
-public interface BookiesListener {
-    void availableBookiesChanged();
-}
+package org.apache.bookkeeper.common;
\ No newline at end of file
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/AuthHandler.java 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/AuthHandler.java
index 9fd739f..6a4dff7 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/AuthHandler.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/AuthHandler.java
@@ -43,8 +43,6 @@ import org.apache.bookkeeper.client.BKException;
 import org.apache.bookkeeper.proto.BookkeeperProtocol.AuthMessage;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.apache.bookkeeper.client.ClientConnectionPeer;
-import org.apache.bookkeeper.bookie.BookieConnectionPeer;
 
 class AuthHandler {
     static final Logger LOG = LoggerFactory.getLogger(AuthHandler.class);
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieConnectionPeer.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieConnectionPeer.java
similarity index 91%
rename from 
bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieConnectionPeer.java
rename to 
bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieConnectionPeer.java
index 63a5e7d..b28c847 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/bookie/BookieConnectionPeer.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieConnectionPeer.java
@@ -18,9 +18,7 @@
  * under the License.
  *
  */
-package org.apache.bookkeeper.bookie;
-
-import org.apache.bookkeeper.proto.ConnectionPeer;
+package org.apache.bookkeeper.proto;
 
 /**
  * Represents the connection to a BookKeeper client, from the Bookie side.
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieNettyServer.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieNettyServer.java
index f725dca..7dd8f6e 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieNettyServer.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/BookieNettyServer.java
@@ -68,7 +68,6 @@ import java.net.SocketAddress;
 import java.util.Collection;
 import java.util.Collections;
 import org.apache.bookkeeper.auth.BookKeeperPrincipal;
-import org.apache.bookkeeper.bookie.BookieConnectionPeer;
 import com.google.common.util.concurrent.ThreadFactoryBuilder;
 import org.apache.bookkeeper.net.BookieSocketAddress;
 
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/ClientConnectionPeer.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/ClientConnectionPeer.java
similarity index 91%
rename from 
bookkeeper-server/src/main/java/org/apache/bookkeeper/client/ClientConnectionPeer.java
rename to 
bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/ClientConnectionPeer.java
index 322cba9..ad556f5 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/client/ClientConnectionPeer.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/ClientConnectionPeer.java
@@ -18,9 +18,7 @@
  * under the License.
  *
  */
-package org.apache.bookkeeper.client;
-
-import org.apache.bookkeeper.proto.ConnectionPeer;
+package org.apache.bookkeeper.proto;
 
 /**
  * Represents the connection to a Bookie, from the client side
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClient.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClient.java
index 9ba75d1..b3dc998 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClient.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/PerChannelBookieClient.java
@@ -19,10 +19,15 @@ package org.apache.bookkeeper.proto;
 
 import static org.apache.bookkeeper.client.LedgerHandle.INVALID_ENTRY_ID;
 
+import com.google.common.collect.Sets;
+import com.google.protobuf.ByteString;
+import com.google.protobuf.ExtensionRegistry;
 import io.netty.bootstrap.Bootstrap;
 import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
 import io.netty.buffer.PooledByteBufAllocator;
 import io.netty.buffer.Unpooled;
+import io.netty.buffer.UnpooledByteBufAllocator;
 import io.netty.channel.Channel;
 import io.netty.channel.ChannelFuture;
 import io.netty.channel.ChannelFutureListener;
@@ -46,27 +51,24 @@ import io.netty.handler.codec.TooLongFrameException;
 import io.netty.util.HashedWheelTimer;
 import io.netty.util.Timeout;
 import io.netty.util.TimerTask;
-
-
 import java.io.IOException;
+import java.net.SocketAddress;
 import java.nio.channels.ClosedChannelException;
 import java.util.ArrayDeque;
 import java.util.Collections;
 import java.util.Collection;
+import java.util.Objects;
 import java.util.Queue;
 import java.util.Set;
-import java.util.Objects;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
-
+import org.apache.bookkeeper.auth.BookKeeperPrincipal;
 import org.apache.bookkeeper.auth.ClientAuthProvider;
-import com.google.protobuf.ByteString;
 import org.apache.bookkeeper.client.BKException;
 import org.apache.bookkeeper.client.BookKeeperClientStats;
 import org.apache.bookkeeper.client.BookieInfoReader.BookieInfo;
-import org.apache.bookkeeper.client.ReadLastConfirmedAndEntryOp;
 import org.apache.bookkeeper.conf.ClientConfiguration;
 import org.apache.bookkeeper.net.BookieSocketAddress;
 import org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.GenericCallback;
@@ -101,19 +103,9 @@ import org.apache.bookkeeper.util.SafeRunnable;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.collect.Sets;
-import com.google.protobuf.ExtensionRegistry;
-import io.netty.buffer.ByteBufAllocator;
-import io.netty.buffer.UnpooledByteBufAllocator;
-import java.net.SocketAddress;
-
-import org.apache.bookkeeper.auth.BookKeeperPrincipal;
-import org.apache.bookkeeper.client.ClientConnectionPeer;
-
 /**
  * This class manages all details of connection to a particular bookie. It also
  * has reconnect logic if a connection to a bookie fails.
- *
  */
 @Sharable
 public class PerChannelBookieClient extends ChannelInboundHandlerAdapter {
@@ -1508,8 +1500,8 @@ public class PerChannelBookieClient extends 
ChannelInboundHandlerAdapter {
         if (maxLAC > INVALID_ENTRY_ID && (rc.ctx instanceof 
ReadEntryCallbackCtx)) {
             ((ReadEntryCallbackCtx) rc.ctx).setLastAddConfirmed(maxLAC);
         }
-        if (lacUpdateTimestamp > -1L && (rc.ctx instanceof 
ReadLastConfirmedAndEntryOp.ReadLastConfirmedAndEntryContext)) {
-            ((ReadLastConfirmedAndEntryOp.ReadLastConfirmedAndEntryContext) 
rc.ctx).setLacUpdateTimestamp(lacUpdateTimestamp);
+        if (lacUpdateTimestamp > -1L && (rc.ctx instanceof 
ReadLastConfirmedAndEntryContext)) {
+            ((ReadLastConfirmedAndEntryContext) 
rc.ctx).setLacUpdateTimestamp(lacUpdateTimestamp);
         }
         rc.cb.readEntryComplete(rcToRet, ledgerId, entryId, buffer, rc.ctx);
     }
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/ReadLastConfirmedAndEntryContext.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/ReadLastConfirmedAndEntryContext.java
new file mode 100644
index 0000000..1bf3685
--- /dev/null
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/proto/ReadLastConfirmedAndEntryContext.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.bookkeeper.proto;
+
+import com.google.common.base.Optional;
+import org.apache.bookkeeper.client.LedgerHandle;
+import org.apache.bookkeeper.net.BookieSocketAddress;
+import 
org.apache.bookkeeper.proto.BookkeeperInternalCallbacks.ReadEntryCallbackCtx;
+
+/**
+ * A {@link ReadEntryCallbackCtx} for long poll read requests.
+ */
+public class ReadLastConfirmedAndEntryContext implements ReadEntryCallbackCtx {
+
+    final int bookieIndex;
+    final BookieSocketAddress bookie;
+    long lac = LedgerHandle.INVALID_ENTRY_ID;
+    Optional<Long> lacUpdateTimestamp = Optional.absent();
+
+    public ReadLastConfirmedAndEntryContext(int bookieIndex, 
BookieSocketAddress bookie) {
+        this.bookieIndex = bookieIndex;
+        this.bookie = bookie;
+    }
+
+    public int getBookieIndex() {
+        return bookieIndex;
+    }
+
+    public BookieSocketAddress getBookieAddress() {
+        return bookie;
+    }
+
+    @Override
+    public void setLastAddConfirmed(long lac) {
+        this.lac = lac;
+    }
+
+    @Override
+    public long getLastAddConfirmed() {
+        return lac;
+    }
+
+    public Optional<Long> getLacUpdateTimestamp() {
+        return lacUpdateTimestamp;
+    }
+
+    public void setLacUpdateTimestamp(long lacUpdateTimestamp) {
+        this.lacUpdateTimestamp = Optional.of(lacUpdateTimestamp);
+    }
+
+}
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/replication/ReplicationWorker.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/replication/ReplicationWorker.java
index 1852089..d3a1415 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/replication/ReplicationWorker.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/replication/ReplicationWorker.java
@@ -133,8 +133,8 @@ public class ReplicationWorker implements Runnable {
         this.underreplicationManager = mFactory
                 .newLedgerUnderreplicationManager();
         this.bkc = BookKeeper.forConfig(new ClientConfiguration(conf))
-                .setZookeeper(zkc)
-                .setStatsLogger(statsLogger.scope(BK_CLIENT_SCOPE))
+                .zk(zkc)
+                .statsLogger(statsLogger.scope(BK_CLIENT_SCOPE))
                 .build();
         this.admin = new BookKeeperAdmin(bkc, statsLogger);
         this.ledgerChecker = new LedgerChecker(bkc);
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLBookieAuthProvider.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLBookieAuthProvider.java
index dff38b7..cb0ca23 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLBookieAuthProvider.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLBookieAuthProvider.java
@@ -28,7 +28,7 @@ import javax.security.sasl.SaslException;
 import org.apache.bookkeeper.auth.AuthCallbacks;
 import org.apache.bookkeeper.auth.AuthToken;
 import org.apache.bookkeeper.auth.BookieAuthProvider;
-import org.apache.bookkeeper.bookie.BookieConnectionPeer;
+import org.apache.bookkeeper.proto.BookieConnectionPeer;
 import org.apache.bookkeeper.client.BKException;
 import org.apache.bookkeeper.conf.ServerConfiguration;
 import org.slf4j.Logger;
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLBookieAuthProviderFactory.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLBookieAuthProviderFactory.java
index b6c2ecd..c2e9ae3 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLBookieAuthProviderFactory.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLBookieAuthProviderFactory.java
@@ -38,7 +38,7 @@ import javax.security.sasl.AuthorizeCallback;
 import javax.security.sasl.RealmCallback;
 import javax.security.sasl.SaslException;
 import org.apache.bookkeeper.auth.AuthCallbacks;
-import org.apache.bookkeeper.bookie.BookieConnectionPeer;
+import org.apache.bookkeeper.proto.BookieConnectionPeer;
 import org.apache.bookkeeper.conf.AbstractConfiguration;
 import org.apache.bookkeeper.conf.ServerConfiguration;
 import org.slf4j.Logger;
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLClientAuthProvider.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLClientAuthProvider.java
index c4a511b..69b94f3 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLClientAuthProvider.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLClientAuthProvider.java
@@ -30,7 +30,7 @@ import org.apache.bookkeeper.auth.AuthCallbacks;
 import org.apache.bookkeeper.auth.AuthToken;
 import org.apache.bookkeeper.auth.ClientAuthProvider;
 import org.apache.bookkeeper.client.BKException;
-import org.apache.bookkeeper.client.ClientConnectionPeer;
+import org.apache.bookkeeper.proto.ClientConnectionPeer;
 import org.slf4j.LoggerFactory;
 
 public class SASLClientAuthProvider implements ClientAuthProvider {
diff --git 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLClientProviderFactory.java
 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLClientProviderFactory.java
index 0278efa..c7b0f96 100644
--- 
a/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLClientProviderFactory.java
+++ 
b/bookkeeper-server/src/main/java/org/apache/bookkeeper/sasl/SASLClientProviderFactory.java
@@ -30,7 +30,7 @@ import javax.security.auth.login.LoginException;
 import javax.security.sasl.SaslException;
 import org.apache.bookkeeper.auth.AuthCallbacks;
 import org.apache.bookkeeper.auth.ClientAuthProvider;
-import org.apache.bookkeeper.client.ClientConnectionPeer;
+import org.apache.bookkeeper.proto.ClientConnectionPeer;
 import org.apache.bookkeeper.conf.AbstractConfiguration;
 import org.apache.bookkeeper.conf.ClientConfiguration;
 import org.slf4j.LoggerFactory;
diff --git 
a/bookkeeper-server/src/test/java/org/apache/bookkeeper/auth/TestAuth.java 
b/bookkeeper-server/src/test/java/org/apache/bookkeeper/auth/TestAuth.java
index 878422c..62a07da 100644
--- a/bookkeeper-server/src/test/java/org/apache/bookkeeper/auth/TestAuth.java
+++ b/bookkeeper-server/src/test/java/org/apache/bookkeeper/auth/TestAuth.java
@@ -42,8 +42,8 @@ import static org.junit.Assert.*;
 
 import org.junit.Test;
 import org.apache.bookkeeper.client.BKException.BKNotEnoughBookiesException;
-import org.apache.bookkeeper.client.ClientConnectionPeer;
-import org.apache.bookkeeper.bookie.BookieConnectionPeer;
+import org.apache.bookkeeper.proto.ClientConnectionPeer;
+import org.apache.bookkeeper.proto.BookieConnectionPeer;
 
 
 public class TestAuth extends BookKeeperClusterTestCase {
diff --git 
a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuthAutoRecoveryTest.java
 
b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuthAutoRecoveryTest.java
index 49b1800..75ea9c8 100644
--- 
a/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuthAutoRecoveryTest.java
+++ 
b/bookkeeper-server/src/test/java/org/apache/bookkeeper/replication/AuthAutoRecoveryTest.java
@@ -34,7 +34,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static org.junit.Assert.*;
-import org.apache.bookkeeper.client.ClientConnectionPeer;
+import org.apache.bookkeeper.proto.ClientConnectionPeer;
 
 /**
  * This test verifies the auditor bookie scenarios from the auth point-of-view
diff --git a/bookkeeper-stats/pom.xml b/bookkeeper-stats/pom.xml
index b67e6bf..4534834 100644
--- a/bookkeeper-stats/pom.xml
+++ b/bookkeeper-stats/pom.xml
@@ -66,6 +66,30 @@
           </execution>
         </executions>
       </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+        <version>${maven-javadoc-plugin.version}</version>
+        <configuration>
+          <!-- Avoid for missing javadoc comments to be marked as errors -->
+          <additionalparam>-Xdoclint:none</additionalparam>
+          <subpackages>org.apache.bookkeeper.stats</subpackages>
+          <groups>
+            <group>
+              <title>Bookkeeper Stats API</title>
+              <packages>org.apache.bookkeeper.stats</packages>
+            </group>
+          </groups>
+        </configuration>
+        <executions>
+          <execution>
+            <id>attach-javadocs</id>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
     </plugins>
   </build>
   <dependencies>
diff --git a/pom.xml b/pom.xml
index 2c06878..df266df 100644
--- a/pom.xml
+++ b/pom.xml
@@ -104,6 +104,8 @@
     <findbugs-maven-plugin.version>3.0.3</findbugs-maven-plugin.version>
     <puppycrawl.checkstyle.version>6.19</puppycrawl.checkstyle.version>
     <maven-checkstyle-plugin.version>2.17</maven-checkstyle-plugin.version>
+    <maven-javadoc-plugin.version>2.10.4</maven-javadoc-plugin.version>
+    <maven-source-plugin.version>2.2.1</maven-source-plugin.version>
   </properties>
   <build>
     <plugins>
@@ -158,15 +160,25 @@
       <plugin>
         <groupId>org.apache.maven.plugins</groupId>
         <artifactId>maven-javadoc-plugin</artifactId>
-        <version>2.10.3</version>
+        <version>${maven-javadoc-plugin.version}</version>
         <configuration>
           <!-- Avoid for missing javadoc comments to be marked as errors -->
           <additionalparam>-Xdoclint:none</additionalparam>
-          
<subpackages>org.apache.bookkeeper.client:org.apache.bookkeeper.conf</subpackages>
+          
<subpackages>org.apache.bookkeeper.client:org.apache.bookkeeper.common.annotation:org.apache.bookkeeper.conf:org.apache.bookkeeper.feature:org.apache.bookkeeper.stats</subpackages>
           <groups>
             <group>
-              <title>Bookkeeper</title>
-              <packages>org.apache.bookkeeper*</packages>
+              <title>Bookkeeper Client</title>
+              
<packages>org.apache.bookkeeper.client:org.apache.bookkeeper.common.annotation:org.apache.bookkeeper.conf:org.apache.bookkeeper.feature</packages>
+            </group>
+            <group>
+              <title>Bookkeeper Stats API</title>
+              <!-- currently codahale and prometheus are placed under `stats` 
package unfortunately.
+                   we might consider rename them to their own packages in 
future. -->
+              <packages>org.apache.bookkeeper.stats</packages>
+            </group>
+            <group>
+              <title>Bookkeeper Stats Providers</title>
+              
<packages>org.apache.bookkeeper.stats.twitter.finagle:org.apache.bookkeeper.stats.twitter.ostrich:org.apache.bookkeeper.stats.twitter.science</packages>
             </group>
           </groups>
         </configuration>
@@ -181,6 +193,19 @@
         </executions>
       </plugin>
       <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-source-plugin</artifactId>
+        <version>${maven-source-plugin.version}</version>
+        <executions>
+          <execution>
+            <id>attach-sources</id>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+      <plugin>
         <artifactId>maven-assembly-plugin</artifactId>
         <version>2.2.1</version>
         <configuration>

-- 
To stop receiving notification emails like this one, please contact
['"[email protected]" <[email protected]>'].

Reply via email to