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

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


The following commit(s) were added to refs/heads/master by this push:
     new 210725e  REST refactoring.
210725e is described below

commit 210725ebc14a727351673a5656bc8e41bf4870f1
Author: JamesBognar <[email protected]>
AuthorDate: Mon Feb 1 15:50:21 2021 -0500

    REST refactoring.
---
 .../java/org/apache/juneau/rest/RestContext.java   |  36 ++-
 .../apache/juneau/rest/SwaggerProviderBuilder.java |  22 +-
 .../rest/logging/BasicDisabledRestLogger.java      |  11 +-
 .../juneau/rest/logging/BasicRestLogger.java       | 352 +++++++++++++++++---
 .../rest/logging/BasicTestCaptureRestLogger.java   |  33 +-
 .../juneau/rest/logging/BasicTestRestLogger.java   |  10 +-
 .../org/apache/juneau/rest/logging/RestLogger.java | 357 +--------------------
 .../juneau/rest/logging/RestLoggerBuilder.java     |  66 ++--
 .../juneau/rest/logging/RestLoggerRuleBuilder.java |   2 +-
 9 files changed, 446 insertions(+), 443 deletions(-)

diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
index 699b333..49e9b9a 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContext.java
@@ -3925,14 +3925,18 @@ public class RestContext extends BeanContext {
                if (resource instanceof RestLogger)
                        x = (RestLogger)resource;
 
-               if (x == null)
-                       x = getInstanceProperty(REST_callLogger, 
RestLogger.class, null, beanFactory);
+               Object o = getProperty(REST_callLogger);
+               if (o instanceof RestLogger)
+                       x = (RestLogger)o;
 
                if (x == null)
                        x = beanFactory.getBean(RestLogger.class).orElse(null);
 
-               if (x == null)
-                       x = getInstanceProperty(REST_callLoggerDefault, 
RestLogger.class, null, beanFactory);
+               if (x == null) {
+                       o = getProperty(REST_callLoggerDefault);
+                       if (o instanceof RestLogger)
+                               x = (RestLogger)o;
+               }
 
                if (x == null)
                        x = createCallLoggerBuilder(resource, 
beanFactory).build();
@@ -3959,18 +3963,36 @@ public class RestContext extends BeanContext {
         * @return The call logger builder for this REST resource.
         * @throws Exception If call logger builder could not be instantiated.
         */
+       @SuppressWarnings("unchecked")
        protected RestLoggerBuilder createCallLoggerBuilder(Object resource, 
BeanFactory beanFactory) throws Exception {
 
+               Class<? extends RestLogger> c = null;
+
+               Object o = getProperty(REST_callLogger);
+               if (o instanceof Class)
+                       c = (Class<? extends RestLogger>)o;
+
+               if (c == null) {
+                       o = getProperty(REST_callLoggerDefault);
+                       if (o instanceof Class)
+                               c = (Class<? extends RestLogger>)o;
+               }
+
+               if (c == null)
+                       c = BasicRestLogger.class;
+
                RestLoggerBuilder x = RestLogger
                        .create()
+                       .beanFactory(beanFactory)
+                       .implClass(c)
                        .normalRules(  // Rules when debugging is not enabled.
-                               RestLogger.createRule()  // Log 500+ errors 
with status-line and header information.
+                               RestLoggerRule.create()  // Log 500+ errors 
with status-line and header information.
                                        .statusFilter(a -> a >= 500)
                                        .level(SEVERE)
                                        .requestDetail(HEADER)
                                        .responseDetail(HEADER)
                                        .build(),
-                               RestLogger.createRule()  // Log 400-500 errors 
with just status-line information.
+                               RestLoggerRule.create()  // Log 400-500 errors 
with just status-line information.
                                        .statusFilter(a -> a >= 400)
                                        .level(WARNING)
                                        .requestDetail(STATUS_LINE)
@@ -3978,7 +4000,7 @@ public class RestContext extends BeanContext {
                                        .build()
                        )
                        .debugRules(  // Rules when debugging is enabled.
-                               RestLogger.createRule()  // Log everything with 
full details.
+                               RestLoggerRule.create()  // Log everything with 
full details.
                                        .level(SEVERE)
                                        .requestDetail(ENTITY)
                                        .responseDetail(ENTITY)
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerProviderBuilder.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerProviderBuilder.java
index d99693b..76c801c 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerProviderBuilder.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/SwaggerProviderBuilder.java
@@ -73,6 +73,17 @@ public class SwaggerProviderBuilder {
        }
 
        /**
+        * Specifies a subclass of {@link SwaggerProvider} to create when the 
{@link #build()} method is called.
+        *
+        * @param value The new value for this setting.
+        * @return  This object (for method chaining).
+        */
+       public SwaggerProviderBuilder implClass(Class<? extends 
SwaggerProvider> value) {
+               this.implClass = value;
+               return this;
+       }
+
+       /**
         * Specifies the variable resolver to use for the {@link 
SwaggerProvider} object.
         *
         * @param value The new value for this setting.
@@ -115,15 +126,4 @@ public class SwaggerProviderBuilder {
                this.fileFinder = value;
                return this;
        }
-
-       /**
-        * Specifies a subclass of {@link SwaggerProvider} to create when the 
{@link #build()} method is called.
-        *
-        * @param value The new value for this setting.
-        * @return  This object (for method chaining).
-        */
-       public SwaggerProviderBuilder implClass(Class<? extends 
SwaggerProvider> value) {
-               this.implClass = value;
-               return this;
-       }
 }
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicDisabledRestLogger.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicDisabledRestLogger.java
index 4a83481..612c4e1 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicDisabledRestLogger.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicDisabledRestLogger.java
@@ -12,8 +12,6 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.rest.logging;
 
-import java.util.function.*;
-
 import org.apache.juneau.rest.*;
 
 /**
@@ -23,12 +21,7 @@ import org.apache.juneau.rest.*;
  *     <li class='link'>{@doc RestLoggingAndDebugging}
  * </ul>
  */
-public class BasicDisabledRestLogger extends RestLogger {
-
-       /**
-        * Returns a builder with the settings used by this logger.
-        */
-       public static final Supplier<RestLoggerBuilder> SETTINGS = 
()->create().disabled();
+public class BasicDisabledRestLogger extends BasicRestLogger {
 
        /**
         * Constructor.
@@ -36,6 +29,6 @@ public class BasicDisabledRestLogger extends RestLogger {
         * @param context The context of the resource object.
         */
        public BasicDisabledRestLogger(RestContext context) {
-               super(create().disabled());
+               super(RestLogger.create().disabled());
        }
 }
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicRestLogger.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicRestLogger.java
index fb88866..9290efc 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicRestLogger.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicRestLogger.java
@@ -12,24 +12,50 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.rest.logging;
 
+import static org.apache.juneau.internal.ObjectUtils.*;
+import static org.apache.juneau.internal.StringUtils.*;
 import static org.apache.juneau.rest.logging.RestLoggingDetail.*;
+import static org.apache.juneau.Enablement.*;
+import static org.apache.juneau.SystemProperties.*;
+import static java.util.logging.Level.*;
 
+import java.util.*;
 import java.util.function.*;
+import java.util.logging.*;
 
-import static java.util.logging.Level.*;
+import javax.servlet.http.*;
 
+import org.apache.juneau.*;
+import org.apache.juneau.collections.*;
+import org.apache.juneau.internal.*;
+import org.apache.juneau.json.*;
 import org.apache.juneau.rest.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.util.*;
+import org.apache.juneau.utils.*;
 
 /**
- * Default implementation of a {@link RestLogger} with typically handling.
+ * Basic implementation of a {@link RestLogger} for logging HTTP requests.
+ *
+ * <p>
+ * Provides the following capabilities:
+ * <ul>
+ *     <li>Allows incoming HTTP requests to be logged at various {@link 
Enablement detail levels}.
+ *     <li>Allows rules to be defined to handle request logging differently 
depending on the resulting status code.
+ *     <li>Allows use of stack trace hashing to eliminate duplication of stack 
traces in log files.
+ *     <li>Allows customization of handling of where requests are logged to.
+ *     <li>Allows configuration via system properties or environment variables.
+ * </ul>
  *
  * <p>
- * Uses the following builder settings:
+ * The following is an example of a logger that logs errors only when 
debugging is not enabled, and everything when
+ * logging is enabled.
+ *
+ * <h5 class='section'>Example:</h5>
  * <p class='bcode w800'>
- *             RestLogger
+ *             RestLogger <jv>logger</jv> = RestLogger
  *                     .<jsm>create</jsm>()
- *                     .logger(<jv>context</jv>.getLogger())  <jc>// Use 
logger registered on REST context.</jc>
- *                     .stackTraceStore(<jv>context</jv>.getStackTraceStore()) 
 <jc>// Use stack trace store registered on REST context.</jc>
+ *                     .logger(<js>"MyLogger"</js>)  <jc>// Use MyLogger Java 
logger.</jc>
  *                     .normalRules(  <jc>// Rules when debugging is not 
enabled.</jc>
  *                             <jsm>createRule</jsm>()  <jc>// Log 500+ errors 
with status-line and header information.</jc>
  *                                     .statusFilter(x -&gt; x &gt;= 500)
@@ -51,52 +77,306 @@ import org.apache.juneau.rest.*;
  *                                     .responseDetail(<jsf>ENTITY</jsf>)
  *                                     .build()
  *                     )
+ *                     .build()
  *             ;
  * </p>
  *
  * <ul class='seealso'>
+ *     <li class='jf'>{@link RestContext#REST_callLogger}
+ *     <li class='jf'>{@link RestContext#REST_callLoggerDefault}
+ *     <li class='jf'>{@link RestContext#REST_debug}
+ *     <li class='jf'>{@link RestContext#REST_debugOn}
+ *     <li class='ja'>{@link Rest#debug}
+ *     <li class='ja'>{@link RestOp#debug}
  *     <li class='link'>{@doc RestLoggingAndDebugging}
  * </ul>
  */
-public class BasicRestLogger extends RestLogger {
+public class BasicRestLogger implements RestLogger {
+
+       private static final RestLoggerRule DEFAULT_RULE = 
RestLoggerRule.create().build();
+
+       private final Logger logger;
+       private final StackTraceStore stackTraceStore;
+       private final RestLoggerRule[] normalRules, debugRules;
+       private final Enablement enabled;
+       private final Predicate<HttpServletRequest> enabledTest;
+       private final Level level;
+       private final RestLoggingDetail requestDetail, responseDetail;
 
        /**
-        * Returns a builder with the settings used by this logger.
+        * Constructor.
+        *
+        * @param builder The builder object.
         */
-       public static final Supplier<RestLoggerBuilder> SETTINGS = 
()->builder();
+       public BasicRestLogger(RestLoggerBuilder builder) {
+               this.logger = firstNonNull(builder.logger, 
Logger.getLogger(getProperty(String.class, SP_logger, "global")));
+               this.stackTraceStore = builder.stackTraceDatabase;
+               this.normalRules = builder.normalRules.toArray(new 
RestLoggerRule[builder.normalRules.size()]);
+               this.debugRules = builder.debugRules.toArray(new 
RestLoggerRule[builder.debugRules.size()]);
+               this.enabled = firstNonNull(builder.enabled, 
getProperty(Enablement.class, SP_enabled, ALWAYS));
+               this.enabledTest = firstNonNull(builder.enabledTest, x -> 
false);
+               this.requestDetail = firstNonNull(builder.requestDetail, 
getProperty(RestLoggingDetail.class, SP_requestDetail, STATUS_LINE));
+               this.responseDetail = firstNonNull(builder.responseDetail, 
getProperty(RestLoggingDetail.class, SP_responseDetail, STATUS_LINE));
+               this.level = firstNonNull(builder.level, 
getProperty(Level.class, SP_level, OFF));
+       }
 
        /**
-        * Constructor.
+        * Called at the end of a servlet request to log the request.
         *
-        * @param context The context of the resource object.
+        * @param req The servlet request.
+        * @param res The servlet response.
         */
-       public BasicRestLogger(RestContext context) {
-               
super(builder().logger(context.getLogger()).stackTraceStore(context.getStackTraceStore()));
+       @Override /* RestLogger */
+       public void log(HttpServletRequest req, HttpServletResponse res) {
+
+               RestLoggerRule rule = getRule(req, res);
+
+               if (! isEnabled(rule, req))
+                       return;
+
+               Level level = firstNonNull(rule.getLevel(), this.level);
+
+               if (level == Level.OFF)
+                       return;
+
+               Throwable e = castOrNull(req.getAttribute("Exception"), 
Throwable.class);
+               Long execTime = castOrNull(req.getAttribute("ExecTime"), 
Long.class);
+
+               RestLoggingDetail reqd = firstNonNull(rule.getRequestDetail(), 
requestDetail);
+               RestLoggingDetail resd = firstNonNull(rule.getResponseDetail(), 
responseDetail);
+
+               String method = req.getMethod();
+               int status = res.getStatus();
+               String uri = req.getRequestURI();
+               byte[] reqBody = getRequestBody(req);
+               byte[] resBody = getResponseBody(req, res);
+
+               StringBuilder sb = new StringBuilder();
+
+               if (reqd != STATUS_LINE || resd != STATUS_LINE)
+                       sb.append("\n=== HTTP Call (incoming) 
======================================================\n");
+
+               StackTraceInfo sti = getStackTraceInfo(e);
+
+               sb.append('[').append(status);
+
+               if (sti != null) {
+                       int count = sti.getCount();
+                       
sb.append(',').append(sti.getHash()).append('.').append(count);
+                       if (count > 1)
+                               e = null;
+               }
+
+               sb.append("] ");
+
+               sb.append("HTTP ").append(method).append(' ').append(uri);
+
+               if (reqd != STATUS_LINE || resd != STATUS_LINE) {
+
+                       if (reqd.isOneOf(HEADER, ENTITY)) {
+                               String qs = req.getQueryString();
+                               if (qs != null)
+                                       sb.append('?').append(qs);
+                       }
+
+                       if (reqBody != null && reqd.isOneOf(HEADER ,ENTITY))
+                               sb.append("\n\tRequest length: 
").append(reqBody.length).append(" bytes");
+
+                       if (resd.isOneOf(HEADER, ENTITY))
+                               sb.append("\n\tResponse code: ").append(status);
+
+                       if (resBody != null && resd.isOneOf(HEADER, ENTITY))
+                               sb.append("\n\tResponse length: 
").append(resBody.length).append(" bytes");
+
+                       if (execTime != null && resd.isOneOf(HEADER, ENTITY))
+                               sb.append("\n\tExec time: 
").append(execTime).append("ms");
+
+                       if (reqd.isOneOf(HEADER, ENTITY)) {
+                               Enumeration<String> hh = req.getHeaderNames();
+                               if (hh.hasMoreElements()) {
+                                       sb.append("\n---Request Headers---");
+                                       while (hh.hasMoreElements()) {
+                                               String h = hh.nextElement();
+                                               
sb.append("\n\t").append(h).append(": ").append(req.getHeader(h));
+                                       }
+                               }
+                       }
+
+                       if (resd.isOneOf(HEADER, ENTITY)) {
+                               Collection<String> hh = res.getHeaderNames();
+                               if (hh.size() > 0) {
+                                       sb.append("\n---Response Headers---");
+                                       for (String h : hh) {
+                                               
sb.append("\n\t").append(h).append(": ").append(res.getHeader(h));
+                                       }
+                               }
+                       }
+
+                       if (reqBody != null && reqBody.length > 0 && reqd == 
ENTITY) {
+                               try {
+                                       sb.append("\n---Request Body UTF-8---");
+                                       sb.append("\n").append(new 
String(reqBody, IOUtils.UTF8));
+                                       sb.append("\n---Request Body Hex---");
+                                       
sb.append("\n").append(toSpacedHex(reqBody));
+                               } catch (Exception e1) {
+                                       
sb.append("\n").append(e1.getLocalizedMessage());
+                               }
+                       }
+
+                       if (resBody != null && resBody.length > 0 && resd == 
ENTITY) {
+                               try {
+                                       sb.append("\n---Response Body 
UTF-8---");
+                                       sb.append("\n").append(new 
String(resBody, IOUtils.UTF8));
+                                       sb.append("\n---Response Body Hex---");
+                                       
sb.append("\n").append(toSpacedHex(resBody));
+                               } catch (Exception e1) {
+                                       sb.append(e1.getLocalizedMessage());
+                               }
+                       }
+                       sb.append("\n=== END 
======================================================================");
+               }
+
+               if (rule.isLogStackTrace() && e == null)
+                       e = new Throwable("Stacktrace");
+
+               log(level, sb.toString(), e);
+
        }
 
-       private static RestLoggerBuilder builder() {
-               return create()
-                       .normalRules(  // Rules when debugging is not enabled.
-                               createRule()  // Log 500+ errors with 
status-line and header information.
-                                       .statusFilter(x -> x >= 500)
-                                       .level(SEVERE)
-                                       .requestDetail(HEADER)
-                                       .responseDetail(HEADER)
-                                       .build(),
-                               createRule()  // Log 400-500 errors with just 
status-line information.
-                                       .statusFilter(x -> x >= 400)
-                                       .level(WARNING)
-                                       .requestDetail(STATUS_LINE)
-                                       .responseDetail(STATUS_LINE)
-                                       .build()
-                       )
-                       .debugRules(  // Rules when debugging is enabled.
-                               createRule()  // Log everything with full 
details.
-                                       .level(SEVERE)
-                                       .requestDetail(ENTITY)
-                                       .responseDetail(ENTITY)
-                                       .build()
-                       )
+       /**
+        * Given the specified servlet request/response, find the rule that 
applies to it.
+        *
+        * <p>
+        * This method can be overridden to provide specialized logic for 
finding rules.
+        *
+        * @param req The servlet request.
+        * @param res The servlet response.
+        * @return The applicable logging rule, or the default rule if not 
found.  Never <jk>null</jk>.
+        */
+       protected RestLoggerRule getRule(HttpServletRequest req, 
HttpServletResponse res) {
+               for (RestLoggerRule r : isDebug(req) ? debugRules : normalRules)
+                       if (r.matches(req, res))
+                               return r;
+               return DEFAULT_RULE;
+       }
+
+       /**
+        * Returns <jk>true</jk> if debug is enabled on this request.
+        *
+        * <p>
+        * Looks for the request attribute <js>"Debug"</js> to determine 
whether debug is enabled.
+        *
+        * <p>
+        * This method can be overridden to provide specialized logic for 
determining whether debug mode is enabled on a request.
+        *
+        * @param req The HTTP request being logged.
+        * @return <jk>true</jk> if debug is enabled on this request.
+        * @see RestContext#REST_debug
+        * @see RestContext#REST_debugOn
+        * @see Rest#debug()
+        * @see RestOp#debug()
+        */
+       protected boolean isDebug(HttpServletRequest req) {
+               return firstNonNull(castOrNull(req.getAttribute("Debug"), 
Boolean.class), false);
+       }
+
+       /**
+        * Returns <jk>true</jk> if logging is enabled for this request.
+        *
+        * <p>
+        * Uses the enabled and enabled-test settings on the matched rule and 
this logger to determine whether a REST
+        * call should be logged.
+        *
+        * <p>
+        * This method can be overridden to provide specialized logic for 
determining whether a REST call should be logged.
+        *
+        * @param rule The first matching rule.  Never <jk>null</jk>.
+        * @param req The HTTP request.
+        * @return <jk>true</jk> if logging is enabled for this request.
+        */
+       protected boolean isEnabled(RestLoggerRule rule, HttpServletRequest 
req) {
+               Enablement enabled = firstNonNull(rule.getEnabled(), 
this.enabled);
+               Predicate<HttpServletRequest> enabledTest = 
firstNonNull(rule.getEnabledTest(), this.enabledTest);
+               return enabled.isEnabled(enabledTest.test(req));
+       }
+
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // Other methods
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       /**
+        * Returns the logger to use for logging REST calls.
+        *
+        * <p>
+        * Returns the logger specified in the builder, or {@link 
Logger#getGlobal()} if it wasn't specified.
+        *
+        * <p>
+        * This method can be overridden in subclasses to provide a different 
logger.
+        *
+        * @return The logger to use for logging REST calls.
+        */
+       protected Logger getLogger() {
+               return logger;
+       }
+
+       /**
+        * Logs the specified message to the logger.
+        *
+        * <p>
+        * Subclasses can override this method to capture messages being sent 
to the logger and handle it differently.
+        *
+        * @param level The log level.
+        * @param msg The log message.
+        * @param e The exception.
+        */
+       protected void log(Level level, String msg, Throwable e) {
+               getLogger().log(level, msg, e);
+       }
+
+       private byte[] getRequestBody(HttpServletRequest req) {
+               if (req instanceof RestRequest)
+                       req = ((RestRequest)req).getInner();
+               if (req instanceof CachingHttpServletRequest)
+                       return ((CachingHttpServletRequest)req).getBody();
+               return castOrNull(req.getAttribute("RequestBody"), 
byte[].class);
+       }
+
+       private byte[] getResponseBody(HttpServletRequest req, 
HttpServletResponse res) {
+               if (res instanceof RestResponse)
+                       res = ((RestResponse)res).getInner();
+               if (res instanceof CachingHttpServletResponse)
+                       return ((CachingHttpServletResponse)res).getBody();
+               return castOrNull(req.getAttribute("ResponseBody"), 
byte[].class);
+       }
+
+       private StackTraceInfo getStackTraceInfo(Throwable e) {
+               if (e == null || stackTraceStore == null)
+                       return null;
+               stackTraceStore.add(e);
+               return stackTraceStore.getStackTraceInfo(e);
+       }
+
+       /**
+        * Returns the properties defined on this bean context as a simple map 
for debugging purposes.
+        *
+        * @return A new map containing the properties defined on this context.
+        */
+       public OMap toMap() {
+               return OMap.create()
+                       .a("logger", logger)
+                       .a("stackTraceStore", stackTraceStore)
+                       .a("enabled", enabled)
+                       .a("level", level)
+                       .a("requestDetail", requestDetail)
+                       .a("responseDetail", responseDetail)
+                       .a("normalRules", normalRules.length == 0 ? null : 
normalRules)
+                       .a("debugRules", debugRules.length == 0 ? null : 
debugRules)
                ;
        }
+
+       @Override /* Object */
+       public String toString() {
+               return SimpleJsonSerializer.DEFAULT_READABLE.toString(toMap());
+       }
 }
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestCaptureRestLogger.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestCaptureRestLogger.java
index 13c5a89..ff395ab 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestCaptureRestLogger.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestCaptureRestLogger.java
@@ -12,6 +12,9 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.rest.logging;
 
+import static java.util.logging.Level.*;
+import static org.apache.juneau.rest.logging.RestLoggingDetail.*;
+
 import java.util.concurrent.atomic.*;
 import java.util.logging.*;
 
@@ -62,7 +65,7 @@ import org.apache.juneau.assertions.*;
  * }
  * </p>
  */
-public class BasicTestCaptureRestLogger extends RestLogger {
+public class BasicTestCaptureRestLogger extends BasicRestLogger {
 
        private AtomicReference<LogRecord> lastRecord = new AtomicReference<>();
 
@@ -81,7 +84,33 @@ public class BasicTestCaptureRestLogger extends RestLogger {
         * Uses the same settings as {@link BasicRestLogger}.
         */
        public BasicTestCaptureRestLogger() {
-               super(BasicRestLogger.SETTINGS.get());
+               super(builder());
+       }
+
+       private static RestLoggerBuilder builder() {
+               return RestLogger.create()
+                       .normalRules(  // Rules when debugging is not enabled.
+                               RestLoggerRule.create()  // Log 500+ errors 
with status-line and header information.
+                                       .statusFilter(x -> x >= 500)
+                                       .level(SEVERE)
+                                       .requestDetail(HEADER)
+                                       .responseDetail(HEADER)
+                                       .build(),
+                               RestLoggerRule.create()  // Log 400-500 errors 
with just status-line information.
+                                       .statusFilter(x -> x >= 400)
+                                       .level(WARNING)
+                                       .requestDetail(STATUS_LINE)
+                                       .responseDetail(STATUS_LINE)
+                                       .build()
+                       )
+                       .debugRules(  // Rules when debugging is enabled.
+                               RestLoggerRule.create()  // Log everything with 
full details.
+                                       .level(SEVERE)
+                                       .requestDetail(ENTITY)
+                                       .responseDetail(ENTITY)
+                                       .build()
+                       )
+               ;
        }
 
        @Override
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestRestLogger.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestRestLogger.java
index 97dc96d..ab9260f 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestRestLogger.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/BasicTestRestLogger.java
@@ -47,7 +47,7 @@ import org.apache.juneau.rest.*;
  *     <li class='link'>{@doc RestLoggingAndDebugging}
  * </ul>
  */
-public class BasicTestRestLogger extends RestLogger {
+public class BasicTestRestLogger extends BasicRestLogger {
 
        /**
         * Constructor.
@@ -59,9 +59,9 @@ public class BasicTestRestLogger extends RestLogger {
        }
 
        private static RestLoggerBuilder builder() {
-               return create()
+               return RestLogger.create()
                        .normalRules(  // Rules when debugging is not enabled.
-                               createRule()  // Log 500+ errors with 
status-line and header information.
+                               RestLoggerRule.create()  // Log 500+ errors 
with status-line and header information.
                                        .statusFilter(x -> x >= 400)
                                        .level(SEVERE)
                                        .requestDetail(HEADER)
@@ -70,7 +70,7 @@ public class BasicTestRestLogger extends RestLogger {
                                        .enabledTest(x -> ! isNoLog(x))  // 
Only log if it's not a no-trace request.
                                        .logStackTrace()
                                        .build(),
-                               createRule()  // Log 400-500 errors with just 
status-line information.
+                               RestLoggerRule.create()  // Log 400-500 errors 
with just status-line information.
                                        .statusFilter(x -> x >= 400)
                                        .level(WARNING)
                                        .requestDetail(STATUS_LINE)
@@ -81,7 +81,7 @@ public class BasicTestRestLogger extends RestLogger {
                                        .build()
                        )
                        .debugRules(  // Rules when debugging is enabled.
-                               createRule()  // Log everything with full 
details.
+                               RestLoggerRule.create()  // Log everything with 
full details.
                                        .level(SEVERE)
                                        .requestDetail(ENTITY)
                                        .responseDetail(ENTITY)
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLogger.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLogger.java
index 520637a..ecf2eb7 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLogger.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLogger.java
@@ -12,76 +12,20 @@
 // 
***************************************************************************************************************************
 package org.apache.juneau.rest.logging;
 
-import static org.apache.juneau.internal.ObjectUtils.*;
-import static org.apache.juneau.internal.StringUtils.*;
-import static org.apache.juneau.rest.logging.RestLoggingDetail.*;
-import static org.apache.juneau.Enablement.*;
-import static org.apache.juneau.SystemProperties.*;
-import static java.util.logging.Level.*;
-
-import java.util.*;
 import java.util.function.*;
 import java.util.logging.*;
 
 import javax.servlet.http.*;
 
 import org.apache.juneau.*;
-import org.apache.juneau.collections.*;
-import org.apache.juneau.internal.*;
-import org.apache.juneau.json.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.rest.annotation.*;
-import org.apache.juneau.rest.util.*;
-import org.apache.juneau.utils.*;
 
 /**
- * Interface class used for logging HTTP requests to the log file.
- *
- * <p>
- * Provides the following capabilities:
- * <ul>
- *     <li>Allows incoming HTTP requests to be logged at various {@link 
Enablement detail levels}.
- *     <li>Allows rules to be defined to handle request logging differently 
depending on the resulting status code.
- *     <li>Allows use of stack trace hashing to eliminate duplication of stack 
traces in log files.
- *     <li>Allows customization of handling of where requests are logged to.
- *     <li>Allows configuration via system properties or environment variables.
- * </ul>
- *
- * <p>
- * The following is an example of a logger that logs errors only when 
debugging is not enabled, and everything when
- * logging is enabled.
- *
- * <h5 class='section'>Example:</h5>
- * <p class='bcode w800'>
- *             RestLogger
- *                     .<jsm>create</jsm>()
- *                     .logger(<js>"MyLogger"</js>)  <jc>// Use MyLogger Java 
logger.</jc>
- *                     .normalRules(  <jc>// Rules when debugging is not 
enabled.</jc>
- *                             <jsm>createRule</jsm>()  <jc>// Log 500+ errors 
with status-line and header information.</jc>
- *                                     .statusFilter(x -&gt; x &gt;= 500)
- *                                     .level(<jsf>SEVERE</jsf>)
- *                                     .requestDetail(<jsf>HEADER</jsf>)
- *                                     .responseDetail<jsf>(HEADER</jsf>)
- *                                     .build(),
- *                             <jsm>createRule</jsm>()  <jc>// Log 400-500 
errors with just status-line information.</jc>
- *                                     .statusFilter(x -&gt; x &gt;= 400)
- *                                     .level(<jsf>WARNING</jsf>)
- *                                     .requestDetail(<jsf>STATUS_LINE</jsf>)
- *                                     .responseDetail(<jsf>STATUS_LINE</jsf>)
- *                                     .build()
- *                     )
- *                     .debugRules(  <jc>// Rules when debugging is 
enabled.</jc>
- *                             <jsm>createRule</jsm>()  <jc>// Log everything 
with full details.</jc>
- *                                     .level(<jsf>SEVERE</jsf>)
- *                                     .requestDetail(<jsf>ENTITY</jsf>)
- *                                     .responseDetail(<jsf>ENTITY</jsf>)
- *                                     .build()
- *                     )
- *             ;
- * </p>
+ * Interface class used for logging HTTP requests.
  *
  * <p>
- * The {@link RestLoggerBuilder#build(Class)} method has been provided for 
easy extension of this class.
+ * The {@link RestLoggerBuilder#implClass(Class)} method has been provided for 
easy extension of this class.
  *
  * <p>
  * The following default implementations are also provided:
@@ -102,16 +46,10 @@ import org.apache.juneau.utils.*;
  *     <li class='link'>{@doc RestLoggingAndDebugging}
  * </ul>
  */
-public class RestLogger {
+public interface RestLogger {
 
        /** Represents no logger */
-       public static final class Null extends RestLogger {
-               Null(RestLoggerBuilder builder) {
-                       super(create());
-               }
-       }
-
-       private static final RestLoggerRule DEFAULT_RULE = 
RestLoggerRule.create().build();
+       public abstract class Null implements RestLogger {}
 
        /**
         * System property name for the default logger name to use for {@link 
RestLogger} objects.
@@ -193,295 +131,10 @@ public class RestLogger {
        }
 
        /**
-        * Creates a new rule builder.
-        *
-        * @return A new rule builder.
-        */
-       public static RestLoggerRuleBuilder createRule() {
-               return new RestLoggerRuleBuilder();
-       }
-
-       private final Logger logger;
-       private final StackTraceStore stackTraceStore;
-       private final RestLoggerRule[] normalRules, debugRules;
-       private final Enablement enabled;
-       private final Predicate<HttpServletRequest> enabledTest;
-       private final Level level;
-       private final RestLoggingDetail requestDetail, responseDetail;
-
-       /**
-        * Constructor.
-        *
-        * @param builder The builder object.
-        */
-       public RestLogger(RestLoggerBuilder builder) {
-               this.logger = firstNonNull(builder.logger, 
Logger.getLogger(getProperty(String.class, SP_logger, "global")));
-               this.stackTraceStore = builder.stackTraceDatabase;
-               this.normalRules = builder.normalRules.toArray(new 
RestLoggerRule[builder.normalRules.size()]);
-               this.debugRules = builder.debugRules.toArray(new 
RestLoggerRule[builder.debugRules.size()]);
-               this.enabled = firstNonNull(builder.enabled, 
getProperty(Enablement.class, SP_enabled, ALWAYS));
-               this.enabledTest = firstNonNull(builder.enabledTest, x -> 
false);
-               this.requestDetail = firstNonNull(builder.requestDetail, 
getProperty(RestLoggingDetail.class, SP_requestDetail, STATUS_LINE));
-               this.responseDetail = firstNonNull(builder.responseDetail, 
getProperty(RestLoggingDetail.class, SP_responseDetail, STATUS_LINE));
-               this.level = firstNonNull(builder.level, 
getProperty(Level.class, SP_level, OFF));
-       }
-
-       /**
         * Called at the end of a servlet request to log the request.
         *
         * @param req The servlet request.
         * @param res The servlet response.
         */
-       public void log(HttpServletRequest req, HttpServletResponse res) {
-
-               RestLoggerRule rule = getRule(req, res);
-
-               if (! isEnabled(rule, req))
-                       return;
-
-               Level level = firstNonNull(rule.getLevel(), this.level);
-
-               if (level == Level.OFF)
-                       return;
-
-               Throwable e = castOrNull(req.getAttribute("Exception"), 
Throwable.class);
-               Long execTime = castOrNull(req.getAttribute("ExecTime"), 
Long.class);
-
-               RestLoggingDetail reqd = firstNonNull(rule.getRequestDetail(), 
requestDetail);
-               RestLoggingDetail resd = firstNonNull(rule.getResponseDetail(), 
responseDetail);
-
-               String method = req.getMethod();
-               int status = res.getStatus();
-               String uri = req.getRequestURI();
-               byte[] reqBody = getRequestBody(req);
-               byte[] resBody = getResponseBody(req, res);
-
-               StringBuilder sb = new StringBuilder();
-
-               if (reqd != STATUS_LINE || resd != STATUS_LINE)
-                       sb.append("\n=== HTTP Call (incoming) 
======================================================\n");
-
-               StackTraceInfo sti = getStackTraceInfo(e);
-
-               sb.append('[').append(status);
-
-               if (sti != null) {
-                       int count = sti.getCount();
-                       
sb.append(',').append(sti.getHash()).append('.').append(count);
-                       if (count > 1)
-                               e = null;
-               }
-
-               sb.append("] ");
-
-               sb.append("HTTP ").append(method).append(' ').append(uri);
-
-               if (reqd != STATUS_LINE || resd != STATUS_LINE) {
-
-                       if (reqd.isOneOf(HEADER, ENTITY)) {
-                               String qs = req.getQueryString();
-                               if (qs != null)
-                                       sb.append('?').append(qs);
-                       }
-
-                       if (reqBody != null && reqd.isOneOf(HEADER ,ENTITY))
-                               sb.append("\n\tRequest length: 
").append(reqBody.length).append(" bytes");
-
-                       if (resd.isOneOf(HEADER, ENTITY))
-                               sb.append("\n\tResponse code: ").append(status);
-
-                       if (resBody != null && resd.isOneOf(HEADER, ENTITY))
-                               sb.append("\n\tResponse length: 
").append(resBody.length).append(" bytes");
-
-                       if (execTime != null && resd.isOneOf(HEADER, ENTITY))
-                               sb.append("\n\tExec time: 
").append(execTime).append("ms");
-
-                       if (reqd.isOneOf(HEADER, ENTITY)) {
-                               Enumeration<String> hh = req.getHeaderNames();
-                               if (hh.hasMoreElements()) {
-                                       sb.append("\n---Request Headers---");
-                                       while (hh.hasMoreElements()) {
-                                               String h = hh.nextElement();
-                                               
sb.append("\n\t").append(h).append(": ").append(req.getHeader(h));
-                                       }
-                               }
-                       }
-
-                       if (resd.isOneOf(HEADER, ENTITY)) {
-                               Collection<String> hh = res.getHeaderNames();
-                               if (hh.size() > 0) {
-                                       sb.append("\n---Response Headers---");
-                                       for (String h : hh) {
-                                               
sb.append("\n\t").append(h).append(": ").append(res.getHeader(h));
-                                       }
-                               }
-                       }
-
-                       if (reqBody != null && reqBody.length > 0 && reqd == 
ENTITY) {
-                               try {
-                                       sb.append("\n---Request Body UTF-8---");
-                                       sb.append("\n").append(new 
String(reqBody, IOUtils.UTF8));
-                                       sb.append("\n---Request Body Hex---");
-                                       
sb.append("\n").append(toSpacedHex(reqBody));
-                               } catch (Exception e1) {
-                                       
sb.append("\n").append(e1.getLocalizedMessage());
-                               }
-                       }
-
-                       if (resBody != null && resBody.length > 0 && resd == 
ENTITY) {
-                               try {
-                                       sb.append("\n---Response Body 
UTF-8---");
-                                       sb.append("\n").append(new 
String(resBody, IOUtils.UTF8));
-                                       sb.append("\n---Response Body Hex---");
-                                       
sb.append("\n").append(toSpacedHex(resBody));
-                               } catch (Exception e1) {
-                                       sb.append(e1.getLocalizedMessage());
-                               }
-                       }
-                       sb.append("\n=== END 
======================================================================");
-               }
-
-               if (rule.isLogStackTrace() && e == null)
-                       e = new Throwable("Stacktrace");
-
-               log(level, sb.toString(), e);
-
-       }
-
-       /**
-        * Given the specified servlet request/response, find the rule that 
applies to it.
-        *
-        * <p>
-        * This method can be overridden to provide specialized logic for 
finding rules.
-        *
-        * @param req The servlet request.
-        * @param res The servlet response.
-        * @return The applicable logging rule, or the default rule if not 
found.  Never <jk>null</jk>.
-        */
-       protected RestLoggerRule getRule(HttpServletRequest req, 
HttpServletResponse res) {
-               for (RestLoggerRule r : isDebug(req) ? debugRules : normalRules)
-                       if (r.matches(req, res))
-                               return r;
-               return DEFAULT_RULE;
-       }
-
-       /**
-        * Returns <jk>true</jk> if debug is enabled on this request.
-        *
-        * <p>
-        * Looks for the request attribute <js>"Debug"</js> to determine 
whether debug is enabled.
-        *
-        * <p>
-        * This method can be overridden to provide specialized logic for 
determining whether debug mode is enabled on a request.
-        *
-        * @param req The HTTP request being logged.
-        * @return <jk>true</jk> if debug is enabled on this request.
-        * @see RestContext#REST_debug
-        * @see RestContext#REST_debugOn
-        * @see Rest#debug()
-        * @see RestOp#debug()
-        */
-       protected boolean isDebug(HttpServletRequest req) {
-               return firstNonNull(castOrNull(req.getAttribute("Debug"), 
Boolean.class), false);
-       }
-
-       /**
-        * Returns <jk>true</jk> if logging is enabled for this request.
-        *
-        * <p>
-        * Uses the enabled and enabled-test settings on the matched rule and 
this logger to determine whether a REST
-        * call should be logged.
-        *
-        * <p>
-        * This method can be overridden to provide specialized logic for 
determining whether a REST call should be logged.
-        *
-        * @param rule The first matching rule.  Never <jk>null</jk>.
-        * @param req The HTTP request.
-        * @return <jk>true</jk> if logging is enabled for this request.
-        */
-       protected boolean isEnabled(RestLoggerRule rule, HttpServletRequest 
req) {
-               Enablement enabled = firstNonNull(rule.getEnabled(), 
this.enabled);
-               Predicate<HttpServletRequest> enabledTest = 
firstNonNull(rule.getEnabledTest(), this.enabledTest);
-               return enabled.isEnabled(enabledTest.test(req));
-       }
-
-
-       
//-----------------------------------------------------------------------------------------------------------------
-       // Other methods
-       
//-----------------------------------------------------------------------------------------------------------------
-
-       /**
-        * Returns the logger to use for logging REST calls.
-        *
-        * <p>
-        * Returns the logger specified in the builder, or {@link 
Logger#getGlobal()} if it wasn't specified.
-        *
-        * <p>
-        * This method can be overridden in subclasses to provide a different 
logger.
-        *
-        * @return The logger to use for logging REST calls.
-        */
-       protected Logger getLogger() {
-               return logger;
-       }
-
-       /**
-        * Logs the specified message to the logger.
-        *
-        * <p>
-        * Subclasses can override this method to capture messages being sent 
to the logger and handle it differently.
-        *
-        * @param level The log level.
-        * @param msg The log message.
-        * @param e The exception.
-        */
-       protected void log(Level level, String msg, Throwable e) {
-               getLogger().log(level, msg, e);
-       }
-
-       private byte[] getRequestBody(HttpServletRequest req) {
-               if (req instanceof RestRequest)
-                       req = ((RestRequest)req).getInner();
-               if (req instanceof CachingHttpServletRequest)
-                       return ((CachingHttpServletRequest)req).getBody();
-               return castOrNull(req.getAttribute("RequestBody"), 
byte[].class);
-       }
-
-       private byte[] getResponseBody(HttpServletRequest req, 
HttpServletResponse res) {
-               if (res instanceof RestResponse)
-                       res = ((RestResponse)res).getInner();
-               if (res instanceof CachingHttpServletResponse)
-                       return ((CachingHttpServletResponse)res).getBody();
-               return castOrNull(req.getAttribute("ResponseBody"), 
byte[].class);
-       }
-
-       private StackTraceInfo getStackTraceInfo(Throwable e) {
-               if (e == null || stackTraceStore == null)
-                       return null;
-               stackTraceStore.add(e);
-               return stackTraceStore.getStackTraceInfo(e);
-       }
-
-       /**
-        * Returns the properties defined on this bean context as a simple map 
for debugging purposes.
-        *
-        * @return A new map containing the properties defined on this context.
-        */
-       public OMap toMap() {
-               return OMap.create()
-                       .a("logger", logger)
-                       .a("stackTraceStore", stackTraceStore)
-                       .a("enabled", enabled)
-                       .a("level", level)
-                       .a("requestDetail", requestDetail)
-                       .a("responseDetail", responseDetail)
-                       .a("normalRules", normalRules.length == 0 ? null : 
normalRules)
-                       .a("debugRules", debugRules.length == 0 ? null : 
debugRules)
-               ;
-       }
-
-       @Override /* Object */
-       public String toString() {
-               return SimpleJsonSerializer.DEFAULT_READABLE.toString(toMap());
-       }
+       public void log(HttpServletRequest req, HttpServletResponse res);
 }
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerBuilder.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerBuilder.java
index 74e4155..41dfefe 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerBuilder.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerBuilder.java
@@ -13,6 +13,8 @@
 package org.apache.juneau.rest.logging;
 
 import static org.apache.juneau.Enablement.*;
+import static org.apache.juneau.internal.ClassUtils.*;
+import static org.apache.juneau.rest.HttpRuntimeException.*;
 
 import java.util.*;
 import java.util.function.*;
@@ -22,11 +24,12 @@ import javax.servlet.http.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.collections.*;
-import org.apache.juneau.reflect.*;
+import org.apache.juneau.cp.*;
+import org.apache.juneau.http.exception.*;
 import org.apache.juneau.utils.*;
 
 /**
- * Builder class for {@link RestLogger} objects.
+ * Builder class for {@link BasicRestLogger} objects.
  */
 public class RestLoggerBuilder {
 
@@ -37,33 +40,56 @@ public class RestLoggerBuilder {
        Predicate<HttpServletRequest> enabledTest;
        RestLoggingDetail requestDetail, responseDetail;
        Level level;
+       BeanFactory beanFactory;
+       Class<? extends RestLogger> implClass;
 
        /**
-        * Create a new {@link RestLogger} using this builder.
+        * Creates a new {@link RestLogger} object from this builder.
         *
-        * @return A new {@link RestLogger}
+        * <p>
+        * Instantiates an instance of the {@link #implClass(Class) 
implementation class} or
+        * else {@link BasicRestLogger} if implementation class was not 
specified.
+        *
+        * @return A new {@link RestLogger} object.
         */
        public RestLogger build() {
-               return new RestLogger(this);
+               try {
+                       Class<? extends RestLogger> ic = isConcrete(implClass) 
? implClass : getDefaultImplClass();
+                       return 
BeanFactory.of(beanFactory).addBeans(RestLoggerBuilder.class, 
this).createBean(ic);
+               } catch (Exception e) {
+                       throw toHttpException(e, InternalServerError.class);
+               }
        }
 
        /**
-        * Create a new subclass of {@link RestLogger} using this builder.
+        * Specifies the default implementation class if not specified via 
{@link #implClass(Class)}.
         *
-        * <p>
-        * The subclass must have a public constructor that optionally takes in 
a {@link RestLoggerBuilder} (or subclass) object.
+        * @return The default implementation class if not specified via {@link 
#implClass(Class)}.
+        */
+       protected Class<? extends RestLogger> getDefaultImplClass() {
+               return BasicRestLogger.class;
+       }
+
+       /**
+        * Specifies the bean factory to use for instantiating the {@link 
RestLogger} object.
         *
-        * @param c The subclass to instantiate.
-        * @param <T> The subclass to instantiate.
-        * @return A new subclass of {@link RestLogger}
-        * @throws ExecutableException If constructor invocation threw an 
exception.
+        * @param value The new value for this setting.
+        * @return  This object (for method chaining).
         */
-       public <T extends RestLogger> T build(Class<T> c) throws 
ExecutableException {
-               return ClassInfo
-                       .of(c)
-                       .getOptionalPublicConstructorFuzzy(this)
-                       .orElseThrow(()->new ExecutableException(c.getName() + 
"(RestCallLoggerBuilder)"))
-                       .invoke(this);
+       public RestLoggerBuilder beanFactory(BeanFactory value) {
+               this.beanFactory = value;
+               return this;
+       }
+
+       /**
+        * Specifies a subclass of {@link RestLogger} to create when the {@link 
#build()} method is called.
+        *
+        * @param value The new value for this setting.
+        * @return  This object (for method chaining).
+        */
+       public RestLoggerBuilder implClass(Class<? extends RestLogger> value) {
+               this.implClass = value;
+               return this;
        }
 
        /**
@@ -78,7 +104,7 @@ public class RestLoggerBuilder {
         * </ol>
         *
         * <p>
-        * The {@link RestLogger#getLogger()} method can also be overridden to 
provide different logic.
+        * The {@link BasicRestLogger#getLogger()} method can also be 
overridden to provide different logic.
         *
         * @param value
         *      The logger to use for logging the request.
@@ -104,7 +130,7 @@ public class RestLoggerBuilder {
         * </ol>
         *
         * <p>
-        * The {@link RestLogger#getLogger()} method can also be overridden to 
provide different logic.
+        * The {@link BasicRestLogger#getLogger()} method can also be 
overridden to provide different logic.
         *
         * @param value
         *      The logger to use for logging the request.
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerRuleBuilder.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerRuleBuilder.java
index aec9437..8fb4b79 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerRuleBuilder.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logging/RestLoggerRuleBuilder.java
@@ -24,7 +24,7 @@ import org.apache.juneau.rest.*;
  * Builder for {@link RestLoggerRule} objects.
  *
  * <p>
- * See the {@link RestLogger} for usage.
+ * See the {@link BasicRestLogger} for usage.
  *
  * <ul class='seealso'>
  *     <li class='jf'>{@link RestContext#REST_callLogger}

Reply via email to