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 092a1fe  Context API refactoring.
092a1fe is described below

commit 092a1fe67e8daa6465cfa63ece35b23f0fe00276
Author: JamesBognar <[email protected]>
AuthorDate: Sat Sep 11 14:28:10 2021 -0400

    Context API refactoring.
---
 .../main/java/org/apache/juneau/cp/BeanStore.java  |  16 +++
 .../org/apache/juneau/mstat/MethodExecStats.java   |  91 ++++++++++++-
 .../juneau/mstat/MethodExecStatsBuilder.java       | 113 ----------------
 .../org/apache/juneau/mstat/MethodExecStore.java   | 147 +++++++++++++++++++--
 .../juneau/mstat/MethodExecStoreBuilder.java       | 115 ----------------
 .../org/apache/juneau/reflect/ExecutableInfo.java  |  34 +++++
 .../org/apache/juneau/reflect/ReflectFlags.java    |   6 +
 .../java/org/apache/juneau/rest/RestContext.java   |  70 +---------
 .../org/apache/juneau/rest/RestContextBuilder.java |  68 ++++++++++
 .../apache/juneau/mstat/MethodExecStore_Test.java  |  30 ++---
 10 files changed, 363 insertions(+), 327 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java
index ce41fbc..0496d6b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java
@@ -444,6 +444,22 @@ public class BeanStore {
                        }
                }
 
+               if (matchedConstructor == null) {
+                       for (ConstructorInfo cc : ci.getDeclaredConstructors()) 
{
+                               if (cc.isProtected()) {
+                                       List<ClassInfo> missing = 
getMissingParamTypes(cc.getParams());
+                                       if (missing.isEmpty()) {
+                                               if (cc.getParamCount() > 
matchedConstructorParams) {
+                                                       
matchedConstructorParams = cc.getParamCount();
+                                                       matchedConstructor = 
cc.accessible();
+                                               }
+                                       } else {
+                                               msg = ()-> "Protected 
constructor found but could not find prerequisites: " + 
missing.stream().map(x->x.getSimpleName()).collect(Collectors.joining(","));
+                                       }
+                               }
+                       }
+               }
+
                // Look for static-builder/protected-constructor pair.
                if (matchedConstructor == null) {
                        for (ConstructorInfo cc2 : 
ci.getDeclaredConstructors()) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStats.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStats.java
index 537a361..58e41f6 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStats.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStats.java
@@ -13,12 +13,18 @@
 package org.apache.juneau.mstat;
 
 import static java.util.Optional.*;
+import static org.apache.juneau.internal.ClassUtils.*;
+import static org.apache.juneau.internal.ExceptionUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
 
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.atomic.*;
 
+import org.apache.juneau.*;
+import org.apache.juneau.cp.*;
+import org.apache.juneau.internal.*;
+
 /**
  * Method execution statistics.
  *
@@ -45,8 +51,8 @@ public class MethodExecStats {
         *
         * @return A new builder for this object.
         */
-       public static MethodExecStatsBuilder create() {
-               return new MethodExecStatsBuilder();
+       public static Builder create() {
+               return new Builder();
        }
 
        /**
@@ -54,13 +60,92 @@ public class MethodExecStats {
         *
         * @param builder The builder for this object.
         */
-       public MethodExecStats(MethodExecStatsBuilder builder) {
+       protected MethodExecStats(Builder builder) {
                this.guid = new Random().nextLong();
                this.method = builder.method;
                this.thrownStore = 
ofNullable(builder.thrownStore).orElseGet(ThrownStore::new);
        }
 
        /**
+        * Builder for this object.
+        */
+       @FluentSetters
+       public static class Builder {
+
+               Method method;
+               ThrownStore thrownStore;
+
+               Class<? extends MethodExecStats> implClass;
+               BeanStore beanStore;
+
+               /**
+                * Create a new {@link MethodExecStats} using this builder.
+                *
+                * @return A new {@link ThrownStats}
+                */
+               public MethodExecStats build() {
+                       try {
+                               Class<? extends MethodExecStats> ic = 
isConcrete(implClass) ? implClass : MethodExecStats.class;
+                               return 
BeanStore.of(beanStore).addBeans(Builder.class, this).createBean(ic);
+                       } catch (ExecutableException e) {
+                               throw runtimeException(e);
+                       }
+               }
+
+               /**
+                * Specifies the bean store to use for instantiating the {@link 
MethodExecStats} object.
+                *
+                * <p>
+                * Can be used to instantiate {@link MethodExecStats} 
implementations with injected constructor argument beans.
+                *
+                * @param value The new value for this setting.
+                * @return  This object (for method chaining).
+                */
+               @FluentSetter
+               public Builder beanStore(BeanStore value) {
+                       beanStore = value;
+                       return this;
+               }
+
+               /**
+                * Specifies a subclass of {@link MethodExecStats} to create 
when the {@link #build()} method is called.
+                *
+                * @param value The new value for this setting.
+                * @return  This object (for method chaining).
+                */
+               @FluentSetter
+               public Builder implClass(Class<? extends MethodExecStats> 
value) {
+                       implClass = value;
+                       return this;
+               }
+
+               /**
+                * Specifies the Java method.
+                *
+                * @param value The new value for this setting.
+                * @return  This object (for method chaining).
+                */
+               @FluentSetter
+               public Builder method(Method value) {
+                       method = value;
+                       return this;
+               }
+
+               /**
+                * Specifies the thrown store for tracking exceptions.
+                *
+                * @param value The new value for this setting.
+                * @return  This object (for method chaining).
+                */
+               @FluentSetter
+               public Builder thrownStore(ThrownStore value) {
+                       thrownStore = value;
+                       return this;
+               }
+       }
+
+
+       /**
         * Call when task is started.
         *
         * @return This object (for method chaining).
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStatsBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStatsBuilder.java
deleted file mode 100644
index 8d9337f..0000000
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStatsBuilder.java
+++ /dev/null
@@ -1,113 +0,0 @@
-// 
***************************************************************************************************************************
-// * 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.juneau.mstat;
-
-import static org.apache.juneau.internal.ClassUtils.*;
-import static org.apache.juneau.internal.ExceptionUtils.*;
-
-import java.lang.reflect.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.cp.*;
-import org.apache.juneau.internal.*;
-
-/**
- * Builder for {@link MethodExecStats} objects.
- */
-@FluentSetters
-public class MethodExecStatsBuilder {
-
-       Method method;
-       ThrownStore thrownStore;
-
-       Class<? extends MethodExecStats> implClass;
-       BeanStore beanStore;
-
-       /**
-        * Create a new {@link MethodExecStats} using this builder.
-        *
-        * @return A new {@link ThrownStats}
-        */
-       public MethodExecStats build() {
-               try {
-                       Class<? extends MethodExecStats> ic = 
isConcrete(implClass) ? implClass : getDefaultImplClass();
-                       return 
BeanStore.of(beanStore).addBeans(MethodExecStatsBuilder.class, 
this).createBean(ic);
-               } catch (ExecutableException e) {
-                       throw runtimeException(e);
-               }
-       }
-
-       /**
-        * Specifies the default implementation class if not specified via 
{@link #implClass(Class)}.
-        *
-        * @return The default implementation class if not specified via {@link 
#implClass(Class)}.
-        */
-       protected Class<? extends MethodExecStats> getDefaultImplClass() {
-               return MethodExecStats.class;
-       }
-
-       /**
-        * Specifies the bean store to use for instantiating the {@link 
MethodExecStats} object.
-        *
-        * <p>
-        * Can be used to instantiate {@link MethodExecStats} implementations 
with injected constructor argument beans.
-        *
-        * @param value The new value for this setting.
-        * @return  This object (for method chaining).
-        */
-       @FluentSetter
-       public MethodExecStatsBuilder beanStore(BeanStore value) {
-               this.beanStore = value;
-               return this;
-       }
-
-       /**
-        * Specifies a subclass of {@link MethodExecStats} to create when the 
{@link #build()} method is called.
-        *
-        * @param value The new value for this setting.
-        * @return  This object (for method chaining).
-        */
-       @FluentSetter
-       public MethodExecStatsBuilder implClass(Class<? extends 
MethodExecStats> value) {
-               this.implClass = value;
-               return this;
-       }
-
-       /**
-        * Specifies the Java method.
-        *
-        * @param value The new value for this setting.
-        * @return  This object (for method chaining).
-        */
-       @FluentSetter
-       public MethodExecStatsBuilder method(Method value) {
-               this.method = value;
-               return this;
-       }
-
-       /**
-        * Specifies the thrown store for tracking exceptions.
-        *
-        * @param value The new value for this setting.
-        * @return  This object (for method chaining).
-        */
-       @FluentSetter
-       public MethodExecStatsBuilder thrownStore(ThrownStore value) {
-               this.thrownStore = value;
-               return this;
-       }
-
-       // <FluentSetters>
-
-       // </FluentSetters>
-}
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStore.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStore.java
index 39a9a4b..1300150 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStore.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStore.java
@@ -13,11 +13,14 @@
 package org.apache.juneau.mstat;
 
 import static java.util.Optional.*;
+import static org.apache.juneau.internal.ClassUtils.*;
+import static org.apache.juneau.internal.ExceptionUtils.*;
 
 import java.lang.reflect.*;
 import java.util.*;
 import java.util.concurrent.*;
 
+import org.apache.juneau.*;
 import org.apache.juneau.cp.*;
 
 /**
@@ -38,15 +41,8 @@ public class MethodExecStore {
         *
         * @return A new builder for this object.
         */
-       public static MethodExecStoreBuilder create() {
-               return new MethodExecStoreBuilder();
-       }
-
-       /**
-        * Constructor.
-        */
-       public MethodExecStore() {
-               this(create());
+       public static Builder create() {
+               return new Builder();
        }
 
        /**
@@ -54,13 +50,144 @@ public class MethodExecStore {
         *
         * @param builder The store to use for storing thrown exception 
statistics.
         */
-       public MethodExecStore(MethodExecStoreBuilder builder) {
+       protected MethodExecStore(Builder builder) {
                this.beanStore = 
ofNullable(builder.beanStore).orElseGet(()->BeanStore.create().build());
                this.thrownStore = 
ofNullable(builder.thrownStore).orElse(beanStore.getBean(ThrownStore.class).orElseGet(ThrownStore::new));
                this.statsImplClass = builder.statsImplClass;
        }
 
        /**
+        * The builder for this object.
+        */
+       public static class Builder {
+
+               ThrownStore thrownStore;
+               private Class<? extends MethodExecStore> implClass;
+               MethodExecStore impl;
+               BeanStore beanStore;
+               Class<? extends MethodExecStats> statsImplClass;
+
+               /**
+                * Constructor.
+                */
+               protected Builder() {}
+
+               /**
+                * Copy constructor.
+                *
+                * @param copyFrom The builder to copy.
+                */
+               protected Builder(Builder copyFrom) {
+                       thrownStore = copyFrom.thrownStore;
+                       implClass = copyFrom.implClass;
+                       impl = copyFrom.impl;
+                       beanStore = copyFrom.beanStore;
+                       statsImplClass = copyFrom.statsImplClass;
+               }
+
+               /**
+                * Create a new {@link MethodExecStore} using this builder.
+                *
+                * @return A new {@link MethodExecStore}
+                */
+               public MethodExecStore build() {
+                       try {
+                               if (impl != null)
+                                       return impl;
+                               Class<? extends MethodExecStore> ic = 
isConcrete(implClass) ? implClass : MethodExecStore.class;
+                               return 
BeanStore.of(beanStore).addBean(Builder.class, this).createBean(ic);
+                       } catch (ExecutableException e) {
+                               throw runtimeException(e);
+                       }
+               }
+
+               /**
+                * Specifies the bean store to use for instantiating the {@link 
MethodExecStore} object.
+                *
+                * <p>
+                * Can be used to instantiate {@link MethodExecStore} 
implementations with injected constructor argument beans.
+                *
+                * @param value The new value for this setting.
+                * @return  This object.
+                */
+               public Builder beanStore(BeanStore value) {
+                       beanStore = value;
+                       return this;
+               }
+
+               /**
+                * Specifies a subclass of {@link MethodExecStore} to create 
when the {@link #build()} method is called.
+                *
+                * @param value The new value for this setting.
+                * @return  This object.
+                */
+               public Builder implClass(Class<? extends MethodExecStore> 
value) {
+                       implClass = value;
+                       return this;
+               }
+
+               /**
+                * Specifies a subclass of {@link MethodExecStats} to use for 
individual method statistics.
+                *
+                * @param value The new value for this setting.
+                * @return  This object.
+                */
+               public Builder statsImplClass(Class<? extends MethodExecStats> 
value) {
+                       statsImplClass = value;
+                       return this;
+               }
+
+               /**
+                * Specifies the store to use for gathering statistics on 
thrown exceptions.
+                *
+                * <p>
+                * Can be used to capture thrown exception stats across 
multiple {@link MethodExecStore} objects.
+                *
+                * <p>
+                * If not specified, one will be created by default for the 
{@link MethodExecStore} object.
+                *
+                * @param value The store to use for gathering statistics on 
thrown exceptions.
+                * @return This object.
+                */
+               public Builder thrownStore(ThrownStore value) {
+                       thrownStore = value;
+                       return this;
+               }
+
+               /**
+                * Same as {@link #thrownStore(ThrownStore)} but only sets the 
new value if the current value is <jk>null</jk>.
+                *
+                * @param value The new value for this setting.
+                * @return This object.
+                */
+               public Builder thrownStoreOnce(ThrownStore value) {
+                       if (thrownStore == null)
+                               thrownStore = value;
+                       return this;
+               }
+
+               /**
+                * Specifies an already-instantiated bean for the {@link 
#build()} method to return.
+                *
+                * @param value The new value for this setting.
+                * @return This object.
+                */
+               public Builder impl(MethodExecStore value) {
+                       impl = value;
+                       return this;
+               }
+
+               /**
+                * Returns a copy of this builder.
+                *
+                * @return A copy of this builder.
+                */
+               public Builder copy() {
+                       return new Builder(this);
+               }
+       }
+
+       /**
         * Returns the statistics for the specified method.
         *
         * <p>
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStoreBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStoreBuilder.java
deleted file mode 100644
index 04a5d12..0000000
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/mstat/MethodExecStoreBuilder.java
+++ /dev/null
@@ -1,115 +0,0 @@
-// 
***************************************************************************************************************************
-// * 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.juneau.mstat;
-
-import static org.apache.juneau.internal.ClassUtils.*;
-import static org.apache.juneau.internal.ExceptionUtils.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.cp.*;
-import org.apache.juneau.internal.*;
-
-/**
- * Builder for {@link MethodExecStore} objects.
- */
-@FluentSetters
-public class MethodExecStoreBuilder {
-
-       ThrownStore thrownStore;
-       private Class<? extends MethodExecStore> implClass;
-       BeanStore beanStore;
-       Class<? extends MethodExecStats> statsImplClass;
-
-       /**
-        * Create a new {@link MethodExecStore} using this builder.
-        *
-        * @return A new {@link MethodExecStore}
-        */
-       public MethodExecStore build() {
-               try {
-                       Class<? extends MethodExecStore> ic = 
isConcrete(implClass) ? implClass : getDefaultImplClass();
-                       return 
BeanStore.of(beanStore).addBeans(MethodExecStoreBuilder.class, 
this).createBean(ic);
-               } catch (ExecutableException e) {
-                       throw runtimeException(e);
-               }
-       }
-
-       /**
-        * Specifies the default implementation class if not specified via 
{@link #implClass(Class)}.
-        *
-        * @return The default implementation class if not specified via {@link 
#implClass(Class)}.
-        */
-       protected Class<? extends MethodExecStore> getDefaultImplClass() {
-               return MethodExecStore.class;
-       }
-
-       /**
-        * Specifies the bean store to use for instantiating the {@link 
MethodExecStore} object.
-        *
-        * <p>
-        * Can be used to instantiate {@link MethodExecStore} implementations 
with injected constructor argument beans.
-        *
-        * @param value The new value for this setting.
-        * @return  This object (for method chaining).
-        */
-       @FluentSetter
-       public MethodExecStoreBuilder beanStore(BeanStore value) {
-               this.beanStore = value;
-               return this;
-       }
-
-       /**
-        * Specifies a subclass of {@link MethodExecStore} to create when the 
{@link #build()} method is called.
-        *
-        * @param value The new value for this setting.
-        * @return  This object (for method chaining).
-        */
-       @FluentSetter
-       public MethodExecStoreBuilder implClass(Class<? extends 
MethodExecStore> value) {
-               this.implClass = value;
-               return this;
-       }
-
-       /**
-        * Specifies a subclass of {@link MethodExecStats} to use for 
individual method statistics.
-        *
-        * @param value The new value for this setting.
-        * @return  This object (for method chaining).
-        */
-       @FluentSetter
-       public MethodExecStoreBuilder statsImplClass(Class<? extends 
MethodExecStats> value) {
-               this.statsImplClass = value;
-               return this;
-       }
-
-       /**
-        * Specifies the store to use for gathering statistics on thrown 
exceptions.
-        *
-        * <p>
-        * Can be used to capture thrown exception stats across multiple {@link 
MethodExecStore} objects.
-        *
-        * <p>
-        * If not specified, one will be created by default for the {@link 
MethodExecStore} object.
-        *
-        * @param thrownStore The store to use for gathering statistics on 
thrown exceptions.
-        * @return This object (for method chaining).
-        */
-       public MethodExecStoreBuilder thrownStore(ThrownStore thrownStore) {
-               this.thrownStore = thrownStore;
-               return this;
-       }
-
-       // <FluentSetters>
-
-       // </FluentSetters>
-}
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ExecutableInfo.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ExecutableInfo.java
index 8af7baa..6e7d171 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ExecutableInfo.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ExecutableInfo.java
@@ -381,6 +381,14 @@ public abstract class ExecutableInfo {
                                        if (isPublic())
                                                return false;
                                        break;
+                               case PROTECTED:
+                                       if (isNotProtected())
+                                               return false;
+                                       break;
+                               case NOT_PROTECTED:
+                                       if (isProtected())
+                                               return false;
+                                       break;
                                case STATIC:
                                        if (isNotStatic())
                                                return false;
@@ -447,6 +455,14 @@ public abstract class ExecutableInfo {
                                        if (isNotPublic())
                                                return true;
                                        break;
+                               case PROTECTED:
+                                       if (isProtected())
+                                               return true;
+                                       break;
+                               case NOT_PROTECTED:
+                                       if (isNotProtected())
+                                               return true;
+                                       break;
                                case STATIC:
                                        if (isStatic())
                                                return true;
@@ -672,6 +688,24 @@ public abstract class ExecutableInfo {
        }
 
        /**
+        * Returns <jk>true</jk> if this method is protected.
+        *
+        * @return <jk>true</jk> if this method is protected.
+        */
+       public final boolean isProtected() {
+               return Modifier.isProtected(e.getModifiers());
+       }
+
+       /**
+        * Returns <jk>true</jk> if this method is not protected.
+        *
+        * @return <jk>true</jk> if this method is not protected.
+        */
+       public final boolean isNotProtected() {
+               return ! Modifier.isProtected(e.getModifiers());
+       }
+
+       /**
         * Returns <jk>true</jk> if this method is static.
         *
         * @return <jk>true</jk> if this method is static.
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ReflectFlags.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ReflectFlags.java
index 86272d6..7aa05b9 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ReflectFlags.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/reflect/ReflectFlags.java
@@ -23,6 +23,12 @@ public enum ReflectFlags {
        /** NOT_PUBLIC */
        NOT_PUBLIC,
 
+       /** PROTECTED */
+       PROTECTED,
+
+       /** NOT_PROTECTED */
+       NOT_PROTECTED,
+
        /** STATIC */
        STATIC,
 
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 2d38c7e..6473949 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
@@ -264,9 +264,7 @@ public class RestContext extends Context {
 
                        logger = bs.add(Logger.class, builder.logger());
                        thrownStore = bs.add(ThrownStore.class, 
builder.thrownStore().build());
-
-                       methodExecStore = createMethodExecStore(r, builder, bs, 
thrownStore);
-                       bs.addBean(MethodExecStore.class, methodExecStore);
+                       methodExecStore = bs.add(MethodExecStore.class, 
builder.methodExecStore().thrownStoreOnce(thrownStore).build());
 
                        Messages m = messages = createMessages(r, builder);
 
@@ -1207,72 +1205,6 @@ public class RestContext extends Context {
        }
 
        /**
-        * Instantiates the method execution statistics store for this REST 
resource.
-        *
-        * @param resource
-        *      The REST servlet or bean that this context defines.
-        * @param builder
-        *      The builder for this object.
-        * @param beanStore
-        *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link RestContextBuilder#beanStore()}.
-        * @param thrownStore
-        *      The thrown exception statistics store.
-        * @return The stack trace store for this REST resource.
-        * @throws Exception If stack trace store could not be instantiated.
-        */
-       protected MethodExecStore createMethodExecStore(Object resource, 
RestContextBuilder builder, BeanStore beanStore, ThrownStore thrownStore) 
throws Exception {
-
-               MethodExecStore x = 
beanStore.getBean(MethodExecStore.class).orElse(null);
-
-               if (x == null)
-                       x = createMethodExecStoreBuilder(resource, builder, 
beanStore, thrownStore).build();
-
-               x = BeanStore
-                       .of(beanStore, resource)
-                       .addBean(MethodExecStore.class, x)
-                       .beanCreateMethodFinder(MethodExecStore.class, resource)
-                       .find("cxreateMethodExecStore")
-                       .withDefault(x)
-                       .run();
-
-               return x;
-       }
-
-       /**
-        * Instantiates the method execution statistics store for this REST 
resource.
-        *
-        * @param resource
-        *      The REST servlet or bean that this context defines.
-        * @param builder
-        *      The builder for this object.
-        * @param beanStore
-        *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link RestContextBuilder#beanStore()}.
-        * @param thrownStore
-        *      The thrown exception statistics store.
-        * @return The stack trace store for this REST resource.
-        * @throws Exception If stack trace store could not be instantiated.
-        */
-       protected MethodExecStoreBuilder createMethodExecStoreBuilder(Object 
resource, RestContextBuilder builder, BeanStore beanStore, ThrownStore 
thrownStore) throws Exception {
-
-               MethodExecStoreBuilder x = MethodExecStore
-                       .create()
-                       .thrownStore(thrownStore)
-                       .beanStore(beanStore);
-
-               x = BeanStore
-                       .of(beanStore, resource)
-                       .addBean(MethodExecStoreBuilder.class, x)
-                       .beanCreateMethodFinder(MethodExecStoreBuilder.class, 
resource)
-                       .find("createMethodExecStoreBuilder")
-                       .withDefault(x)
-                       .run();
-
-               return x;
-       }
-
-       /**
         * Instantiates the default request headers for this REST object.
         *
         * @param resource
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
index f710c8d..dc1cab6 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/RestContextBuilder.java
@@ -123,6 +123,7 @@ public class RestContextBuilder extends ContextBuilder 
implements ServletConfig
        private VarResolver.Builder varResolver;
        private Logger logger;
        private ThrownStore.Builder thrownStore;
+       private MethodExecStore.Builder methodExecStore;
 
        String
                allowedHeaderParams = env("RestContext.allowedHeaderParams", 
"Accept,Content-Type"),
@@ -885,6 +886,73 @@ public class RestContextBuilder extends ContextBuilder 
implements ServletConfig
                return v.get();
        }
 
+       /**
+        * Returns the builder for the {@link MethodExecStore} object in the 
REST context.
+        *
+        * @return The builder for the {@link MethodExecStore} object in the 
REST context.
+        */
+       public final MethodExecStore.Builder methodExecStore() {
+               if (methodExecStore == null)
+                       methodExecStore = createMethodExecStore(beanStore(), 
resource());
+               return methodExecStore;
+       }
+
+       /**
+        * Sets the builder for the {@link MethodExecStore} object in the REST 
context.
+        *
+        * @param value The builder for the {@link MethodExecStore} object in 
the REST context.
+        * @return This object.
+        * @throws RuntimeException If {@link #init(Object)} has not been 
called.
+        */
+       public final RestContextBuilder methodExecStore(MethodExecStore value) {
+               methodExecStore().impl(value);
+               return this;
+       }
+
+       /**
+        * Instantiates the method execution statistics store for this REST 
resource.
+        *
+        * @param resource
+        *      The REST servlet or bean that this context defines.
+        * @param beanStore
+        *      The factory used for creating beans and retrieving injected 
beans.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
+        * @return The stack trace store for this REST resource.
+        */
+       protected MethodExecStore.Builder createMethodExecStore(BeanStore 
beanStore, Supplier<?> resource) {
+
+               Value<MethodExecStore.Builder> v = Value.empty();
+               Object r = resource.get();
+
+               beanStore.getBean(MethodExecStore.Builder.class).map(x -> 
x.copy()).ifPresent(x->v.set(x));
+
+               BeanStore
+                       .of(beanStore, r)
+                       .addBean(MethodExecStore.Builder.class, v.get())
+                       .beanCreateMethodFinder(MethodExecStore.Builder.class, 
r)
+                       .find("createMethodExecStore")
+                       .execute()
+                       .ifPresent(x -> v.set(x));
+
+               if (v.isEmpty()) {
+                       v.set(
+                               MethodExecStore
+                                       .create()
+                                       .beanStore(beanStore)
+                       );
+               }
+
+               BeanStore
+                       .of(beanStore, r)
+                       .addBean(MethodExecStore.Builder.class, v.get())
+                       .beanCreateMethodFinder(MethodExecStore.class, r)
+                       .find("createMethodExecStore")
+                       .execute()
+                       .ifPresent(x -> v.get().impl(x));
+
+               return v.get();
+       }
+
        
//----------------------------------------------------------------------------------------------------
        // Methods that give access to the config file, var resolver, and 
properties.
        
//----------------------------------------------------------------------------------------------------
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/mstat/MethodExecStore_Test.java 
b/juneau-utest/src/test/java/org/apache/juneau/mstat/MethodExecStore_Test.java
index 803aacd..3752f7e 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/mstat/MethodExecStore_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/mstat/MethodExecStore_Test.java
@@ -34,26 +34,20 @@ public class MethodExecStore_Test {
                
assertObject(MethodExecStore.create().build()).isType(MethodExecStore.class);
        }
 
-       public static class A1 extends MethodExecStore{}
+       public static class A1 extends MethodExecStore{
+               protected A1(Builder builder) {
+                       super(builder);
+               }
+       }
 
        @Test
        public void a02_builder_implClass() {
                
assertObject(MethodExecStore.create().implClass(A1.class).build()).isType(A1.class);
        }
 
-       @Test
-       public void a03_builder_defaultImplClass() {
-               MethodExecStoreBuilder b = new MethodExecStoreBuilder() {
-                       @Override
-                       protected Class<? extends MethodExecStore> 
getDefaultImplClass() {
-                               return A1.class;
-                       }
-               };
-               assertObject(b.build()).isType(A1.class);
-       }
-
        public static class A4 extends MethodExecStore {
-               public A4(MethodExecStoreBuilder b) throws Exception {
+               public A4(MethodExecStore.Builder b) throws Exception {
+                       super(b);
                        throw new RuntimeException("foobar");
                }
        }
@@ -66,14 +60,16 @@ public class MethodExecStore_Test {
        public static class A5a {}
 
        public static class A5b extends MethodExecStore {
-               public A5b(MethodExecStoreBuilder b, A5a x) throws Exception {
+               public A5b(MethodExecStore.Builder b, A5a x) throws Exception {
+                       super(b);
                        if (x == null)
                                throw new RuntimeException("Bad");
                }
        }
 
        public static class A5c extends MethodExecStore {
-               public A5c(MethodExecStoreBuilder b, Optional<A5a> x) throws 
Exception {
+               public A5c(MethodExecStore.Builder b, Optional<A5a> x) throws 
Exception {
+                       super(b);
                        if (x == null)
                                throw new RuntimeException("Bad");
                }
@@ -95,7 +91,7 @@ public class MethodExecStore_Test {
        public static class A6a {}
 
        public static class A6b extends MethodExecStats {
-               public A6b(MethodExecStatsBuilder b, A6a x) throws Exception {
+               public A6b(MethodExecStats.Builder b, A6a x) throws Exception {
                        super(b);
                        if (x == null)
                                throw new RuntimeException("Bad");
@@ -103,7 +99,7 @@ public class MethodExecStore_Test {
        }
 
        public static class A6c extends MethodExecStats {
-               public A6c(MethodExecStatsBuilder b, Optional<A6a> x) throws 
Exception {
+               public A6c(MethodExecStats.Builder b, Optional<A6a> x) throws 
Exception {
                        super(b);
                        if (x == null)
                                throw new RuntimeException("Bad");

Reply via email to