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

commit f1a0ed4594443c591cd1b284742ed60056c25346
Author: JamesBognar <[email protected]>
AuthorDate: Sat Sep 11 12:16:14 2021 -0400

    Context API refactoring.
---
 .../src/main/java/org/apache/juneau/Value.java     | 148 +++---
 .../main/java/org/apache/juneau/cp/BeanStore.java  |  69 ++-
 .../java/org/apache/juneau/rest/RestContext.java   | 209 ++-------
 .../org/apache/juneau/rest/RestContextBuilder.java | 498 +++++++++++----------
 .../juneau/rest/annotation/RestAnnotation.java     |   1 -
 .../src/test/java/org/apache/juneau/ValueTest.java |  30 --
 6 files changed, 454 insertions(+), 501 deletions(-)

diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Value.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Value.java
index 3d55c32..21a645f 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Value.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Value.java
@@ -13,6 +13,8 @@
 package org.apache.juneau;
 
 import java.lang.reflect.*;
+import java.util.*;
+import java.util.function.*;
 
 import org.apache.juneau.reflect.*;
 
@@ -20,6 +22,9 @@ import org.apache.juneau.reflect.*;
  * Represents a simple settable value.
  *
  * <p>
+ * Similar to an {@link Optional} but mutable.
+ *
+ * <p>
  * This object is not thread safe.
  *
  * @param <T> The value type.
@@ -37,62 +42,19 @@ public class Value<T> {
        }
 
        /**
-        * Returns the generic parameter type of the Value parameter at the 
specified position.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bcode w800'>
-        *      <jk>public class</jk> A {
-        *              <jk>public void</jk> doX(Value&lt;Foo&gt; foo) {...}
-        *      }
-        * </p>
-        * <p class='bcode w800'>
-        *      Class&lt;?&gt; t = 
Value.<jsm>getValueType</jsm>(A.<jk>class</jk>.getMethod(<js>"doX"</js>, 
Value.<jk>class</jk>));
-        *      <jsm>assertTrue</jsm>(t == Foo.<jk>class</jk>);
-        * </p>
+        * Static creator.
         *
-        * @param m The method containing the parameter.
-        * @param i The index of the parameter.
-        * @return The parameter type of the value, or <jk>null</jk> if the 
method parameter is not of type <c>Value</c>.
+        * @return An empty {@link Value} object.
         */
-       public static Type getParameterType(Method m, int i) {
-               return getParameterType(m.getGenericParameterTypes()[i]);
+       public static <T> Value<T> empty() {
+               return new Value<>(null);
        }
 
-       /**
-        * Returns the generic parameter type of the Value type.
-        *
-        * @param t The type to find the parameter type of.
-        * @return The parameter type of the value, or <jk>null</jk> if the 
type is not a subclass of <c>Value</c>.
-        */
-       public static Type getParameterType(Type t) {
-               if (t instanceof ParameterizedType) {
-                       ParameterizedType pt = (ParameterizedType)t;
-                       if (pt.getRawType() == Value.class) {
-                               Type[] ta = pt.getActualTypeArguments();
-                               if (ta.length > 0)
-                                       return ta[0];
-                       }
-               } else if (t instanceof Class) {
-                       Class<?> c = (Class<?>)t;
-                       if (Value.class.isAssignableFrom(c)) {
-                               return ClassInfo.of(c).getParameterType(0, 
Value.class);
-                       }
-               }
 
-               return null;
-       }
+       
//-----------------------------------------------------------------------------------------------------------------
+       // Implementation
+       
//-----------------------------------------------------------------------------------------------------------------
 
-       /**
-        * Convenience method for checking if the specified type is this class.
-        *
-        * @param t The type to check.
-        * @return <jk>true</jk> if the specified type is this class.
-        */
-       public static boolean isType(Type t) {
-               return
-                       (t instanceof ParameterizedType && 
((ParameterizedType)t).getRawType() == Value.class)
-                       || (t instanceof Class && 
Value.class.isAssignableFrom((Class<?>)t));
-       }
 
        private T t;
        private ValueListener<T> listener;
@@ -100,8 +62,7 @@ public class Value<T> {
        /**
         * Constructor.
         */
-       public Value() {
-       }
+       public Value() {}
 
        /**
         * Constructor.
@@ -150,7 +111,88 @@ public class Value<T> {
         *
         * @return <jk>true</jk> if the value is set.
         */
-       public boolean isSet() {
+       public boolean isPresent() {
                return get() != null;
        }
+
+       /**
+        * If a value is present, invoke the specified consumer with the value, 
otherwise do nothing.
+        *
+        * @param consumer Block to be executed if a value is present.
+        */
+       public void ifPresent(Consumer<? super T> consumer) {
+               if (t != null)
+                       consumer.accept(t);
+       }
+
+       /**
+        * Applies a mapping function against the contents of this value.
+        *
+        * @param mapper The mapping function.
+        * @return The mapped value.
+        */
+       public <T2> Value<T2> map(Function<? super T, T2> mapper) {
+               if (t != null)
+                       return Value.of(mapper.apply(t));
+               return Value.empty();
+       }
+
+       /**
+        * Returns the contents of this value or the default value if 
<jk>null</jk>.
+        *
+        * @param def The default value.
+        * @return The contents of this value or the default value if 
<jk>null</jk>.
+        */
+       public T orElse(T def) {
+               return t == null ? def : t;
+       }
+       /**
+        * Returns <jk>true</jk> if the value is empty.
+        *
+        * @return <jk>true</jk> if the value is empty.
+        */
+       public boolean isEmpty() {
+               return t == null;
+       }
+
+       
//-----------------------------------------------------------------------------------------------------------------
+       // Helper methods.
+       
//-----------------------------------------------------------------------------------------------------------------
+
+       /**
+        * Returns the generic parameter type of the Value type.
+        *
+        * @param t The type to find the parameter type of.
+        * @return The parameter type of the value, or <jk>null</jk> if the 
type is not a subclass of <c>Value</c>.
+        */
+       public static Type getParameterType(Type t) {
+               if (t instanceof ParameterizedType) {
+                       ParameterizedType pt = (ParameterizedType)t;
+                       if (pt.getRawType() == Value.class) {
+                               Type[] ta = pt.getActualTypeArguments();
+                               if (ta.length > 0)
+                                       return ta[0];
+                       }
+               } else if (t instanceof Class) {
+                       Class<?> c = (Class<?>)t;
+                       if (Value.class.isAssignableFrom(c)) {
+                               return ClassInfo.of(c).getParameterType(0, 
Value.class);
+                       }
+               }
+
+               return null;
+       }
+
+       /**
+        * Convenience method for checking if the specified type is this class.
+        *
+        * @param t The type to check.
+        * @return <jk>true</jk> if the specified type is this class.
+        */
+       public static boolean isType(Type t) {
+               return
+                       (t instanceof ParameterizedType && 
((ParameterizedType)t).getRawType() == Value.class)
+                       || (t instanceof Class && 
Value.class.isAssignableFrom((Class<?>)t));
+       }
+
 }
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 54e176d..f5836d5 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
@@ -49,9 +49,9 @@ public class BeanStore {
        public static final BeanStore INSTANCE = create().readOnly().build();
 
        private final Map<String,Supplier<?>> beanMap = new 
ConcurrentHashMap<>();
-       private final Optional<BeanStore> parent;
-       private final Optional<Object> outer;
-       private final boolean readOnly;
+       final Optional<BeanStore> parent;
+       final Optional<Object> outer;
+       final boolean readOnly;
 
        /**
         * Static creator.
@@ -94,29 +94,58 @@ public class BeanStore {
         *
         * @param builder The builder containing the settings for this bean.
         */
-       public BeanStore(Builder builder) {
+       protected BeanStore(Builder builder) {
                this.parent = ofNullable(builder.parent);
                this.outer = ofNullable(builder.outer);
                this.readOnly = builder.readOnly;
        }
 
        /**
+        * Creates a copy of this bean store.
+        *
+        * @return A mutable copy of this bean store.
+        */
+       public Builder copy() {
+               return new Builder(this);
+       }
+
+       /**
         * The builder for this object.
         */
        public static class Builder {
 
                Class<? extends BeanStore> implClass = BeanStore.class;
+               BeanStore impl;
                Object outer;
                BeanStore parent;
                boolean readOnly;
 
                /**
+                * Constructor.
+                */
+               protected Builder() {}
+
+               /**
+                * Copy constructor.
+                *
+                * @param copyFrom The bean store to copy from.
+                */
+               protected Builder(BeanStore copyFrom) {
+                       implClass = copyFrom.getClass();
+                       outer = copyFrom.outer.orElse(null);
+                       parent = copyFrom.parent.orElse(null);
+                       readOnly = copyFrom.readOnly;
+               }
+
+               /**
                 * Create a new {@link BeanStore} using this builder.
                 *
                 * @return A new {@link BeanStore}
                 */
                public BeanStore build() {
                        try {
+                               if (impl != null)
+                                       return impl;
                                if (implClass == BeanStore.class)
                                        return new BeanStore(this);
                                Class<? extends BeanStore> ic = 
isConcrete(implClass) ? implClass : BeanStore.class;
@@ -130,7 +159,7 @@ public class BeanStore {
                 * Specifies a subclass of {@link BeanStore} to create when the 
{@link #build()} method is called.
                 *
                 * @param value The new value for this setting.
-                * @return  This object (for method chaining).
+                * @return  This object.
                 */
                @FluentSetter
                public Builder implClass(Class<? extends BeanStore> value) {
@@ -145,7 +174,7 @@ public class BeanStore {
                 * Bean searches are performed recursively up this parent chain.
                 *
                 * @param value The new value for this setting.
-                * @return  This object (for method chaining).
+                * @return  This object.
                 */
                @FluentSetter
                public Builder parent(BeanStore value) {
@@ -159,7 +188,7 @@ public class BeanStore {
                 * <p>
                 * This means methods such as {@link BeanStore#addBean(Class, 
Object)} cannot be used.
                 *
-                * @return  This object (for method chaining).
+                * @return  This object.
                 */
                @FluentSetter
                public Builder readOnly() {
@@ -176,13 +205,27 @@ public class BeanStore {
                 * of the servlet class.
                 *
                 * @param value The new value for this setting.
-                * @return  This object (for method chaining).
+                * @return  This object.
                 */
                @FluentSetter
                public Builder outer(Object value) {
                        outer = value;
                        return this;
                }
+
+               /**
+                * Specifies an implementation of a bean store.
+                *
+                * <p>
+                * Causes the {@link #build()} method to return a predefined 
bean instead of a new one.
+                *
+                * @param value The bean that this builder should return.
+                * @return  This object.
+                */
+               public Builder impl(BeanStore value) {
+                       this.impl = value;
+                       return this;
+               }
        }
 
        /**
@@ -220,7 +263,7 @@ public class BeanStore {
         * @param <T> The class to associate this bean with.
         * @param c The class to associate this bean with.
         * @param t The bean.
-        * @return This object (for method chaining).
+        * @return This object.
         */
        public <T> BeanStore addBean(Class<T> c, T t) {
                assertCanWrite();
@@ -233,7 +276,7 @@ public class BeanStore {
         * @param <T> The class to associate this bean with.
         * @param t The bean.
         * @param name The bean name if this is a named bean.
-        * @return This object (for method chaining).
+        * @return This object.
         */
        public <T> BeanStore addBean(String name, T t) {
                assertCanWrite();
@@ -250,7 +293,7 @@ public class BeanStore {
         * @param <T> The class to associate this bean with.
         * @param c The class to associate this bean with.
         * @param t The bean.
-        * @return This object (for method chaining).
+        * @return This object.
         */
        @SuppressWarnings("unchecked")
        public <T> BeanStore addBeans(Class<T> c, T t) {
@@ -274,7 +317,7 @@ public class BeanStore {
         * @param <T> The class to associate this bean with.
         * @param c The class to associate this bean with.
         * @param t The bean supplier.
-        * @return This object (for method chaining).
+        * @return This object.
         */
        public <T> BeanStore addSupplier(Class<T> c, Supplier<T> t) {
                assertCanWrite();
@@ -287,7 +330,7 @@ public class BeanStore {
         * @param <T> The class to associate this bean with.
         * @param t The bean supplier.
         * @param name The bean name.
-        * @return This object (for method chaining).
+        * @return This object.
         */
        public <T> BeanStore addSupplier(String name, Supplier<T> t) {
                assertCanWrite();
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 556cc2a..0e15306 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
@@ -250,14 +250,17 @@ public class RestContext extends Context {
 
                        RestContext parent = parentContext = 
builder.parentContext;
 
-                       rootBeanStore = createBeanStore(r, builder, parent);
+                       rootBeanStore = builder.beanStore();
 
-                       BeanStore bf = beanStore = BeanStore.of(rootBeanStore, 
r);
-                       bf.addBean(BeanStore.class, bf);
-                       bf.addBean(RestContext.class, this);
-                       bf.addBean(Object.class, r);
-                       bf.addBean(RestContextBuilder.class, builder);
-                       bf.addBean(AnnotationWorkList.class, 
builder.getApplied());
+                       beanStore = rootBeanStore.copy().build();
+                       beanStore
+                               .addBean(BeanStore.class, beanStore)
+                               .addBean(RestContext.class, this)
+                               .addBean(Object.class, r)
+                               .addBean(RestContextBuilder.class, builder)
+                               .addBean(AnnotationWorkList.class, 
builder.getApplied());
+
+                       BeanStore bf = beanStore;
 
                        Logger l = logger = createLogger(r, builder, bf);
                        bf.addBean(Logger.class, l);
@@ -401,120 +404,6 @@ public class RestContext extends Context {
        }
 
        /**
-        * Instantiates the bean store for this REST resource.
-        *
-        * <p>
-        * The bean store is typically used for passing in injected beans into 
REST contexts and for storing beans
-        * created by the REST context.
-        *
-        * <p>
-        * Instantiates based on the following logic:
-        * <ul>
-        *      <li>Returns the resource class itself if it's an instance of 
{@link BeanStore}.
-        *      <li>Looks for bean store set via any of the following:
-        *              <ul>
-        *                      <li>{@link 
RestContextBuilder#beanStore(Class)}/{@link 
RestContextBuilder#beanStore(BeanStore)}
-        *                      <li>{@link Rest#beanStore()}.
-        *              </ul>
-        *      <li>Instantiates a new {@link BeanStore}.
-        *              Uses the parent context's root bean store as the parent 
bean store if this is a child resource.
-        * </ul>
-        *
-        * <p>
-        * Your REST class can also implement a create method called 
<c>createBeanStore()</c> to instantiate your own
-        * bean store.
-        *
-        * <h5 class='figure'>Example:</h5>
-        * <p class='bpcode w800'>
-        *      <ja>@Rest</ja>
-        *      <jk>public class</jk> MyRestClass {
-        *
-        *              <jk>public</jk> BeanStore 
createBeanStore(Optional&lt;BeanStore&gt; <jv>parentBeanStore</jv>) 
<jk>throws</jk> Exception {
-        *                      <jc>// Create your own bean store here.</jc>
-        *              }
-        *      }
-        * </p>
-        *
-        * <p>
-        * The <c>createBeanStore()</c> method can be static or non-static can 
contain any of the following arguments:
-        * <ul>
-        *      <li><c>{@link Optional}&lt;{@link BeanStore}&gt;</c> - The 
parent root bean store if this is a child resource.
-        * </ul>
-        *
-        * @param resource
-        *      The REST servlet or bean that this context defines.
-        * @param builder
-        *      The builder for this object.
-        * @param parent
-        *      The parent context if the REST bean was registered via {@link 
Rest#children()}.
-        *      <br>Will be <jk>null</jk> if the bean is a top-level resource.
-        * @return The bean store for this REST resource.
-        * @throws Exception If bean store could not be instantiated.
-        */
-       protected BeanStore createBeanStore(Object resource, RestContextBuilder 
builder, RestContext parent) throws Exception {
-
-               BeanStore x = null;
-
-               if (resource instanceof BeanStore)
-                       x = (BeanStore)resource;
-
-               if (x == null)
-                       x = builder.beanStoreRef.value().orElse(null);
-
-               if (x == null)
-                       x = createBeanStoreBuilder(resource, builder, 
parent).build();
-
-               x = BeanStore
-                       .of(x, resource)
-                       .addBean(BeanStore.class, x)
-                       .beanCreateMethodFinder(BeanStore.class, resource)
-                       .find("createBeanStore")
-                       .withDefault(x)
-                       .run();
-
-               return x;
-       }
-
-       /**
-        * Instantiates the builder for the {@link BeanStore} for this context.
-        *
-        * @param resource
-        *      The REST servlet or bean that this context defines.
-        * @param builder
-        *      The builder for this object.
-        * @param parent
-        *      The parent context if the REST bean was registered via {@link 
Rest#children()}.
-        *      <br>Will be <jk>null</jk> if the bean is a top-level resource.
-        * @return The bean store builder for this REST resource.
-        * @throws Exception If bean store could not be instantiated.
-        */
-       protected BeanStore.Builder createBeanStoreBuilder(Object resource, 
RestContextBuilder builder, RestContext parent) throws Exception {
-
-               Class<? extends BeanStore> c = 
builder.beanStoreRef.type().orElse(null);
-
-               BeanStore root = parent == null ? null : parent.rootBeanStore;
-
-               BeanStore.Builder x = BeanStore
-                       .create()
-                       .parent(root)
-                       .implClass(c)
-                       .outer(resource);
-
-               x = BeanStore
-                       .create()
-                       .parent(root)
-                       .outer(resource)
-                       .build()
-                       .addBean(BeanStore.Builder.class, x)
-                       .beanCreateMethodFinder(BeanStore.Builder.class, 
resource)
-                       .find("createBeanStoreBuilder")
-                       .withDefault(x)
-                       .run();
-
-               return x;
-       }
-
-       /**
         * Instantiates the file finder for this REST resource.
         *
         * <p>
@@ -529,7 +418,7 @@ public class RestContext extends Context {
         *                      <li>{@link 
RestContextBuilder#fileFinder(Class)}/{@link 
RestContextBuilder#fileFinder(FileFinder)}
         *                      <li>{@link Rest#fileFinder()}.
         *              </ul>
-        *      <li>Resolves it via the {@link 
#createBeanStore(Object,RestContextBuilder,RestContext) bean store} registered 
in this context (including Spring beans if using SpringRestServlet).
+        *      <li>Resolves it via the {@link RestContextBuilder#beanStore() 
bean store} registered in this context (including Spring beans if using 
SpringRestServlet).
         *      <li>Looks for file finder default setting.
         *      <li>Instantiates via {@link 
#createFileFinderBuilder(Object,RestContextBuilder,BeanStore)}.
         * </ul>
@@ -565,7 +454,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The file finder for this REST resource.
         * @throws Exception If file finder could not be instantiated.
         */
@@ -611,7 +500,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The file finder builder for this REST resource.
         * @throws Exception If file finder builder could not be instantiated.
         */
@@ -675,7 +564,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The file finder for this REST resource.
         * @throws Exception If file finder could not be instantiated.
         */
@@ -721,7 +610,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The static files builder for this REST resource.
         * @throws Exception If static files builder could not be instantiated.
         */
@@ -792,7 +681,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @param logger
         *      The Java logger to use for logging messages.
         *      <br>Created by {@link 
#createLogger(Object,RestContextBuilder,BeanStore)}.
@@ -844,7 +733,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @param logger
         *      The Java logger to use for logging messages.
         *      <br>Created by {@link 
#createLogger(Object,RestContextBuilder,BeanStore)}.
@@ -928,7 +817,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The response handlers for this REST resource.
         * @throws Exception If response handlers could not be instantiated.
         */
@@ -976,7 +865,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The HTTP part serializer for this REST resource.
         * @throws Exception If serializer could not be instantiated.
         */
@@ -1027,7 +916,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The HTTP part parser for this REST resource.
         * @throws Exception If parser could not be instantiated.
         */
@@ -1071,7 +960,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The REST method parameter resolvers for this REST resource.
         * @throws Exception If parameter resolvers could not be instantiated.
         */
@@ -1099,7 +988,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The REST method parameter resolvers for this REST resource.
         * @throws Exception If parameter resolvers could not be instantiated.
         */
@@ -1162,7 +1051,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The logger for this REST resource.
         * @throws Exception If logger could not be instantiated.
         */
@@ -1207,7 +1096,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The JSON schema generator for this REST resource.
         * @throws Exception If JSON schema generator could not be instantiated.
         */
@@ -1240,7 +1129,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The JSON-schema generator builder for this REST resource.
         * @throws Exception If JSON-schema generator builder could not be 
instantiated.
         */
@@ -1294,7 +1183,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @param fileFinder The file finder configured on this bean created by 
{@link #createFileFinder(Object,RestContextBuilder,BeanStore)}.
         * @param messages The localized messages configured on this bean 
created by {@link #createMessages(Object,RestContextBuilder)}.
         * @param varResolver The variable resolver configured on this bean.
@@ -1338,7 +1227,7 @@ public class RestContext extends Context {
         *      <br>Consists of all properties gathered through the builder and 
annotations on this class and all parent classes.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @param fileFinder The file finder configured on this bean created by 
{@link #createFileFinder(Object,RestContextBuilder,BeanStore)}.
         * @param messages The localized messages configured on this bean 
created by {@link #createMessages(Object,RestContextBuilder)}.
         * @param varResolver The variable resolver configured on this bean.
@@ -1396,7 +1285,7 @@ public class RestContext extends Context {
         *      <br>Will be <jk>null</jk> if the bean is a top-level resource.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The stack trace store for this REST resource.
         * @throws Exception If stack trace store could not be instantiated.
         */
@@ -1430,7 +1319,7 @@ public class RestContext extends Context {
         *      <br>Will be <jk>null</jk> if the bean is a top-level resource.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The stack trace store for this REST resource.
         * @throws Exception If stack trace store could not be instantiated.
         */
@@ -1463,7 +1352,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @param thrownStore
         *      The thrown exception statistics store.
         *      <br>Created by {@link 
#createThrownStore(Object,RestContextBuilder,RestContext,BeanStore)}.
@@ -1497,7 +1386,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @param thrownStore
         *      The thrown exception statistics store.
         *      <br>Created by {@link 
#createThrownStore(Object,RestContextBuilder,RestContext,BeanStore)}.
@@ -1531,7 +1420,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The default request headers for this REST object.
         * @throws Exception If stack trace store could not be instantiated.
         */
@@ -1559,7 +1448,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The default response headers for this REST object.
         * @throws Exception If stack trace store could not be instantiated.
         */
@@ -1587,7 +1476,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The default response headers for this REST object.
         * @throws Exception If stack trace store could not be instantiated.
         */
@@ -1615,7 +1504,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The debug enablement bean for this REST object.
         * @throws Exception If bean could not be created.
         */
@@ -1655,7 +1544,7 @@ public class RestContext extends Context {
         *      <br>Consists of all properties gathered through the builder and 
annotations on this class and all parent classes.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The debug enablement bean builder for this REST object.
         * @throws Exception If bean builder could not be created.
         */
@@ -1786,7 +1675,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The builder for the {@link RestOperations} object.
         * @throws Exception An error occurred.
         */
@@ -1817,7 +1706,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The REST methods builder for this REST resource.
         * @throws Exception If REST methods builder could not be instantiated.
         */
@@ -1899,7 +1788,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @param servletConfig
         *      The servlet config passed into the servlet by the servlet 
container.
         * @return The builder for the {@link RestChildren} object.
@@ -1932,7 +1821,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @param servletConfig
         *      The servlet config passed into the servlet by the servlet 
container.
         * @return The REST children builder for this REST resource.
@@ -2005,7 +1894,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The default response headers for this REST object.
         * @throws Exception If list could not be instantiated.
         */
@@ -2039,7 +1928,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The default response headers for this REST object.
         * @throws Exception If list could not be instantiated.
         */
@@ -2073,7 +1962,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The default response headers for this REST object.
         * @throws Exception If list could not be instantiated.
         */
@@ -2107,7 +1996,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The default response headers for this REST object.
         * @throws Exception If list could not be instantiated.
         */
@@ -2141,7 +2030,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The default response headers for this REST object.
         * @throws Exception If list could not be instantiated.
         */
@@ -2175,7 +2064,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The default response headers for this REST object.
         * @throws Exception If list could not be instantiated.
         */
@@ -2209,7 +2098,7 @@ public class RestContext extends Context {
         *      The builder for this object.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The default response headers for this REST object.
         * @throws Exception If list could not be instantiated.
         */
@@ -2865,7 +2754,7 @@ public class RestContext extends Context {
         * @param m The Java method being called.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The array of resolvers.
         */
        protected RestOpArg[] findRestOperationArgs(Method m, BeanStore 
beanStore) {
@@ -2901,7 +2790,7 @@ public class RestContext extends Context {
         * @param m The Java method being called.
         * @param beanStore
         *      The factory used for creating beans and retrieving injected 
beans.
-        *      <br>Created by {@link 
#createBeanStore(Object,RestContextBuilder,RestContext)}.
+        *      <br>Created by {@link RestContextBuilder#beanStore()}.
         * @return The array of resolvers.
         */
        protected RestOpArg[] findHookMethodArgs(Method m, BeanStore beanStore) 
{
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 89d12c9..255dd61 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
@@ -63,13 +63,6 @@ import org.apache.juneau.utils.*;
  * An extension of the {@link ServletConfig} object used during servlet 
initialization.
  *
  * <p>
- * Provides access to the following initialized resources:
- * <ul>
- *     <li>{@link #getConfig()} - The external configuration for this resource.
- *     <li>{@link #varResolver()} - The variable resolver for this resource.
- * </ul>
- *
- * <p>
  * Methods are provided for overriding or augmenting the information provided 
by the <ja>@Rest</ja> annotation.
  * In general, most information provided in the <ja>@Rest</ja> annotation can 
be specified programmatically
  * through calls on this object.
@@ -113,7 +106,7 @@ public class RestContextBuilder extends ContextBuilder 
implements ServletConfig
        final ServletConfig inner;
        final Class<?> resourceClass;
        final RestContext parentContext;
-       final BeanStore beanStore;
+       BeanStore beanStore;
 
        
//-----------------------------------------------------------------------------------------------------------------
        // The following fields are meant to be modifiable.
@@ -155,7 +148,6 @@ public class RestContextBuilder extends ContextBuilder 
implements ServletConfig
        BeanRef<StaticFiles> staticFilesDefault = BeanRef.of(StaticFiles.class);
        BeanRef<FileFinder> fileFinder = BeanRef.of(FileFinder.class);
        BeanRef<FileFinder> fileFinderDefault = BeanRef.of(FileFinder.class);
-       BeanRef<BeanStore> beanStoreRef = BeanRef.of(BeanStore.class);
        NamedAttributeList defaultRequestAttributes = 
NamedAttributeList.create();
        HeaderListBuilder defaultRequestHeaders = HeaderList.create();
        HeaderListBuilder defaultResponseHeaders = HeaderList.create();
@@ -229,10 +221,10 @@ public class RestContextBuilder extends ContextBuilder 
implements ServletConfig
 
        /**
         * Constructor.
+        *
         * @param resourceClass The resource class.
         * @param parentContext The parent context if this is a child of 
another resource.
         * @param servletConfig The servlet config if available.
-        *
         * @throws ServletException Initialization failed.
         */
        protected RestContextBuilder(Class<?> resourceClass, RestContext 
parentContext, ServletConfig servletConfig) throws ServletException {
@@ -253,18 +245,19 @@ public class RestContextBuilder extends ContextBuilder 
implements ServletConfig
                                
fileFinderDefault.value(parentContext.fileFinderDefault);
                        }
 
-                       beanStore = createBeanStore(resourceClass, 
parentContext);
-                       beanStore.addBean(RestContextBuilder.class, this);
-                       beanStore.addBean(ServletConfig.class, 
ofNullable(servletConfig).orElse(this));
-                       beanStore.addBean(ServletContext.class, 
ofNullable(servletConfig).orElse(this).getServletContext());
+                       beanStore = createBeanStore(resourceClass, 
parentContext)
+                               .build()
+                               .addBean(RestContextBuilder.class, this)
+                               .addBean(ServletConfig.class, 
ofNullable(servletConfig).orElse(this))
+                               .addBean(ServletContext.class, 
ofNullable(servletConfig).orElse(this).getServletContext());
 
-                       varResolver = createVarResolver(resourceClass, 
beanStore);
+                       varResolver = createVarResolver(beanStore, 
resourceClass);
 
                        VarResolver vr = varResolver.build();
                        beanStore.addBean(VarResolver.class, vr);
 
                        // Find our config file.  It's the last non-empty 
@RestResource(config).
-                       config = createConfig(resourceClass, beanStore);
+                       config = createConfig(beanStore, resourceClass);
                        beanStore.addBean(Config.class, config);
 
                        // Add our config file to the variable resolver.
@@ -298,13 +291,53 @@ public class RestContextBuilder extends ContextBuilder 
implements ServletConfig
        @Override /* BeanContextBuilder */
        public RestContext build() {
                try {
-                       return (RestContext) BeanStore.of(beanStore, 
resource.get()).addBeans(RestContextBuilder.class, 
this).createBean(getContextClass().orElse(RestContext.class));
+                       return (RestContext) BeanStore.of(beanStore(), 
resource.get()).addBeans(RestContextBuilder.class, 
this).createBean(getContextClass().orElse(RestContext.class));
                } catch (Exception e) {
                        throw toHttpException(e, InternalServerError.class);
                }
        }
 
        /**
+        * Performs initialization on this builder.
+        *
+        * Calls all @RestHook(INIT) methods on the specified resource object.
+        *
+        * @param resource The resource bean. Required.
+        * @return This object.
+        * @throws ServletException If hook method calls failed.
+        */
+       public RestContextBuilder init(Object resource) throws ServletException 
{
+               this.resource = resource instanceof Supplier ? 
(Supplier<?>)resource : ()->resource;
+
+               ClassInfo rci = ClassInfo.ofProxy(resource);
+               BeanStore bs = beanStore();
+
+               Map<String,MethodInfo> map = new LinkedHashMap<>();
+               for (MethodInfo m : rci.getAllMethodsParentFirst()) {
+                       if (m.hasAnnotation(RestHook.class) && 
m.getLastAnnotation(RestHook.class).value() == HookEvent.INIT) {
+                               m.setAccessible();
+                               String sig = m.getSignature();
+                               if (! map.containsKey(sig))
+                                       map.put(sig, m);
+                       }
+               }
+               for (MethodInfo m : map.values()) {
+                       List<ParamInfo> params = m.getParams();
+
+                       List<ClassInfo> missing = 
bs.getMissingParamTypes(params);
+                       if (!missing.isEmpty())
+                               throw new RestServletException("Could not call 
@RestHook(INIT) method {0}.{1}.  Could not find prerequisites: {2}.", 
m.getDeclaringClass().getSimpleName(), m.getSignature(), 
missing.stream().map(x->x.getSimpleName()).collect(Collectors.joining(",")));
+
+                       try {
+                               m.invoke(resource, bs.getParams(params));
+                       } catch (Exception e) {
+                               throw new RestServletException(e, "Exception 
thrown from @RestHook(INIT) method {0}.{1}.", 
m.getDeclaringClass().getSimpleName(), m.getSignature());
+                       }
+               }
+               return this;
+       }
+
+       /**
         * Returns access to the bean store being used by this builder.
         *
         * <p>
@@ -322,11 +355,42 @@ public class RestContextBuilder extends ContextBuilder 
implements ServletConfig
         *
         * @return The bean store being used by this builder.
         */
-       protected BeanStore beanStore() {
+       public final BeanStore beanStore() {
                return beanStore;
        }
 
        /**
+        * Sets the bean store for this builder.
+        *
+        * <p>
+        * The resolver used for resolving instances of child resources and 
various other beans including:
+        * <ul>
+        *      <li>{@link RestLogger}
+        *      <li>{@link SwaggerProvider}
+        *      <li>{@link FileFinder}
+        *      <li>{@link StaticFiles}
+        * </ul>
+        *
+        * <p>
+        * Note that the <c>SpringRestServlet</c> classes uses the 
<c>SpringBeanStore</c> class to allow for any
+        * Spring beans to be injected into your REST resources.
+        *
+        * <ul class='seealso'>
+        *      <li class='link'>{@doc RestInjection}
+        * </ul>
+        *
+        * @param value
+        *      The new value for this setting.
+        *      <br>The default is {@link BasicRestLogger}.
+        * @return This object (for method chaining).
+        */
+       @FluentSetter
+       public RestContextBuilder beanStore(BeanStore value) {
+               beanStore = value;
+               return this;
+       }
+
+       /**
         * Creates the bean store for this builder.
         *
         * <p>
@@ -344,21 +408,35 @@ public class RestContextBuilder extends ContextBuilder 
implements ServletConfig
         * @param parentContext The parent context if there is one.
         * @return A new bean store.
         */
-       protected BeanStore createBeanStore(Class<?> resourceClass, RestContext 
parentContext) {
+       protected BeanStore.Builder createBeanStore(Class<?> resourceClass, 
RestContext parentContext) {
 
-               BeanStore x = BeanStore
-                       .of(parentContext == null ? null : 
parentContext.getRootBeanStore())
-                       .beanCreateMethodFinder(BeanStore.class, resourceClass)
-                       .find("createBeanStore")
-                       .run();
+               // Create default builder.
+               Value<BeanStore.Builder> v = 
Value.of(BeanStore.create().parent(parentContext == null ? null : 
parentContext.getRootBeanStore()));
 
-               if (x == null && parentContext != null)
-                       x = parentContext.getRootBeanStore();
+               // Apply @Rest(beanStore).
+               ClassInfo.of(resourceClass)
+                       .getAnnotations(Rest.class)
+                       .stream()
+                       .map(x -> x.beanStore())
+                       .filter(x -> x != BeanStore.Null.class)
+                       .reduce((x1,x2)->x2)
+                       .ifPresent(x -> v.get().implClass(x));
 
-               if (x == null)
-                       x = BeanStore.create().build();
+               // Replace with builder:  public static BeanStore.Builder 
createBeanStore()
+               v.get().build()
+                       .beanCreateMethodFinder(BeanStore.Builder.class, 
resourceClass)
+                       .find("createBeanStore")
+                       .execute()
+                       .ifPresent(x -> v.set(x));
 
-               return x;
+               // Replace with implementations:  public static BeanStore 
createBeanStore()
+               v.get().build()
+                       .beanCreateMethodFinder(BeanStore.class, resourceClass)
+                       .find("createBeanStore")
+                       .execute()
+                       .ifPresent(x -> v.get().impl(x));
+
+               return v.get();
        }
 
        /**
@@ -370,7 +448,7 @@ public class RestContextBuilder extends ContextBuilder 
implements ServletConfig
         * used to resolve string variables of the form <js>"$X{...}"</js> in 
various places such as annotations on the REST class and methods.
         *
         * <p>
-        * The var resolver is created by the constructor using the {@link 
#createVarResolver(Class,BeanStore)} method and is initialized with the 
following beans:
+        * The var resolver is created by the constructor using the {@link 
#createVarResolver(BeanStore,Class)} method and is initialized with the 
following beans:
         * <ul>
         *      <li>{@link ConfigVar}
         *      <li>{@link FileVar}
@@ -393,11 +471,23 @@ public class RestContextBuilder extends ContextBuilder 
implements ServletConfig
         *
         * @return The var resolver builder.
         */
-       protected VarResolver.Builder varResolver() {
+       public final VarResolver.Builder varResolver() {
                return varResolver;
        }
 
        /**
+        * Sets the variable resolver for this builder.
+        *
+        * @param value The new variable resolver.
+        * @return This object (for method chaining).
+        */
+       @FluentSetter
+       public RestContextBuilder varResolver(VarResolver.Builder value) {
+               varResolver = value;
+               return this;
+       }
+
+       /**
         * Creates the var resolver builder.
         *
         * <p>
@@ -417,46 +507,54 @@ public class RestContextBuilder extends ContextBuilder 
implements ServletConfig
         *      <li>
         *              Looks for bean of type {@link 
org.apache.juneau.svl.VarResolver.Builder} in bean store and returns a copy of 
it.
         *      <li>
-        *              Creates a default builder with default variables pulled 
from {@link #createVars(Class,BeanStore)}.
+        *              Creates a default builder with default variables pulled 
from {@link #createVars(BeanStore,Class)}.
         * </ol>
         *
-        * @param resourceClass The resource class.
         * @param beanStore The bean store containing injected beans.
+        * @param resourceClass The resource class.
         * @return A new var resolver builder.
         */
-       protected VarResolver.Builder createVarResolver(Class<?> resourceClass, 
BeanStore beanStore) {
+       protected VarResolver.Builder createVarResolver(BeanStore beanStore, 
Class<?> resourceClass) {
+
+               Value<VarResolver.Builder> v = Value.empty();
 
-               VarResolver.Builder x = BeanStore
+               // Get builder from:  public static VarResolver.Builder 
createVarResolver()
+               BeanStore
                        .of(beanStore)
                        .beanCreateMethodFinder(VarResolver.Builder.class, 
resourceClass)
                        .find("createVarResolver")
-                       .run();
-
-               if (x == null) {
-                       x = beanStore.getBean(VarResolver.Builder.class).map(y 
-> y.copy()).orElse(null);
-               }
-
-               if (x == null) {
-                       x = VarResolver.create()
-                               .defaultVars()
-                               .vars(createVars(resourceClass, beanStore))
-                               .vars(FileVar.class)
-                               .bean(FileFinder.class, 
FileFinder.create().cp(resourceClass,null,true).build());
+                       .execute()
+                       .ifPresent(x -> v.set(x));
+
+               // Get builder from bean store.
+               if (v.isEmpty())
+                       beanStore.getBean(VarResolver.Builder.class).map(y -> 
y.copy()).ifPresent(x -> v.set(x));
+
+               // Create default builder.
+               if (v.isEmpty()) {
+                       v.set(
+                               VarResolver
+                                       .create()
+                                       .defaultVars()
+                                       .vars(createVars(beanStore, 
resourceClass))
+                                       .vars(FileVar.class)
+                                       .bean(FileFinder.class, 
FileFinder.create().cp(resourceClass,null,true).build())
+                       );
                }
 
-               VarResolver.Builder x2 = x;
-
-               beanStore.getBean(VarResolver.class).ifPresent(y -> x2.impl(y));
+               // Get implementation from bean store.
+               beanStore.getBean(VarResolver.class).ifPresent(x -> 
v.get().impl(x));
 
+               // Get implementation from:  public static VarResolver 
createVarResolver()
                BeanStore
                        .of(beanStore)
-                       .addBean(VarResolver.Builder.class, x)
+                       .addBean(VarResolver.Builder.class, v.get())
                        .beanCreateMethodFinder(VarResolver.class, 
resourceClass)
                        .find("createVarResolver")
                        .execute()
-                       .ifPresent(y -> x2.impl(y));
+                       .ifPresent(x -> v.get().impl(x));
 
-               return x2;
+               return v.get();
        }
 
        /**
@@ -474,128 +572,74 @@ public class RestContextBuilder extends ContextBuilder 
implements ServletConfig
         *              Creates a default builder with default variables.
         * </ol>
         *
-        * @param resourceClass The resource class.
         * @param beanStore The bean store containing injected beans.
+        * @param resourceClass The resource class.
         * @return A new var resolver variable list.
         */
-       protected VarList createVars(Class<?> resourceClass, BeanStore 
beanStore) {
-
-               VarList x = beanStore.getBean(VarList.class).map(y -> 
y.copy()).orElse(null);
-
-               if (x == null)
-                       x = VarList.of(
-                               ConfigVar.class,
-                               FileVar.class,
-                               LocalizationVar.class,
-                               RequestAttributeVar.class,
-                               RequestFormDataVar.class,
-                               RequestHeaderVar.class,
-                               RequestPathVar.class,
-                               RequestQueryVar.class,
-                               RequestVar.class,
-                               RequestSwaggerVar.class,
-                               SerializedRequestAttrVar.class,
-                               ServletInitParamVar.class,
-                               SwaggerVar.class,
-                               UrlVar.class,
-                               UrlEncodeVar.class,
-                               HtmlWidgetVar.class
-                       ).addDefault();
-
-               x = BeanStore
+       protected VarList createVars(BeanStore beanStore, Class<?> 
resourceClass) {
+
+               Value<VarList> v = Value.empty();
+
+               // Get implementation from bean store.
+               beanStore.getBean(VarList.class).map(x -> x.copy()).ifPresent(x 
-> v.set(x));
+
+               // Create default.
+               if (v.isEmpty()) {
+                       v.set(
+                               VarList.of(
+                                       ConfigVar.class,
+                                       FileVar.class,
+                                       LocalizationVar.class,
+                                       RequestAttributeVar.class,
+                                       RequestFormDataVar.class,
+                                       RequestHeaderVar.class,
+                                       RequestPathVar.class,
+                                       RequestQueryVar.class,
+                                       RequestVar.class,
+                                       RequestSwaggerVar.class,
+                                       SerializedRequestAttrVar.class,
+                                       ServletInitParamVar.class,
+                                       SwaggerVar.class,
+                                       UrlVar.class,
+                                       UrlEncodeVar.class,
+                                       HtmlWidgetVar.class
+                               )
+                               .addDefault()
+                       );
+               }
+
+               // Get implementation from:  public static VarList createVars()
+               BeanStore
                        .of(beanStore, resourceClass)
-                       .addBean(VarList.class, x)
+                       .addBean(VarList.class, v.get())
                        .beanCreateMethodFinder(VarList.class, resourceClass)
                        .find("createVars")
-                       .withDefault(x)
-                       .run();
+                       .execute()
+                       .ifPresent(x -> v.set(x));
 
-               return x;
+               return v.get();
        }
 
        /**
-        * Creates the config for this builder.
+        * Returns the external configuration file for this resource.
         *
-        * @param resourceClass The resource class.
-        * @param beanStore The bean store to use for creating the config.
-        * @return A new bean store.
-        * @throws Exception If bean store could not be instantiated.
-        */
-       protected Config createConfig(Class<?> resourceClass, BeanStore 
beanStore) throws Exception {
-               ClassInfo rci = ClassInfo.of(resourceClass);
-               Config x = null;
-               Object o = resource == null ? null : resource.get();
-               if (o instanceof Config)
-                       x = (Config)o;
-
-               if (x == null) {
-                       x = BeanStore
-                               .of(beanStore)
-                               .beanCreateMethodFinder(Config.class, 
resourceClass)
-                               .find("createConfig")
-                               .run();
-               }
-
-               if (x == null)
-                       x = beanStore.getBean(Config.class).orElse(null);
-
-               // Find our config file.  It's the last non-empty 
@RestResource(config).
-               String configPath = "";
-               for (AnnotationInfo<Rest> r : 
rci.getAnnotationInfos(Rest.class))
-                       if (! r.getAnnotation().config().isEmpty())
-                               configPath = r.getAnnotation().config();
-               VarResolver vr = 
beanStore.getBean(VarResolver.class).orElseThrow(()->runtimeException("VarResolver
 not found."));
-               String cf = vr.resolve(configPath);
-
-               if (x == null && "SYSTEM_DEFAULT".equals(cf))
-                       x = Config.getSystemDefault();
-
-               if (x == null) {
-                       ConfigBuilder cb = Config.create().varResolver(vr);
-                       if (! cf.isEmpty())
-                               cb.name(cf);
-                       x = cb.build();
-               }
-               return x;
-       }
-
-       /**
-        * Performs initialization on this builder.
+        * <p>
+        * The configuration file location is determined via the {@link 
Rest#config() @Rest(config)}
+        * annotation on the resource.
         *
-        * Calls all @RestHook(INIT) methods on the specified resource object.
+        * <p>
+        * The config file can be programmatically overridden by adding the 
following method to your resource:
+        * <p class='bcode w800'>
+        *      <jk>public</jk> Config createConfig(ServletConfig 
servletConfig) <jk>throws</jk> ServletException;
+        * </p>
         *
-        * @param resource The resource bean. Required.
-        * @return This object.
-        * @throws ServletException If hook method calls failed.
+        * <p>
+        * If a config file is not set up, then an empty config file will be 
returned that is not backed by any file.
+        *
+        * @return The external config file for this resource.  Never 
<jk>null</jk>.
         */
-       public RestContextBuilder init(Object resource) throws ServletException 
{
-               this.resource = resource instanceof Supplier ? 
(Supplier<?>)resource : ()->resource;
-
-               ClassInfo rci = ClassInfo.ofProxy(resource);
-
-               Map<String,MethodInfo> map = new LinkedHashMap<>();
-               for (MethodInfo m : rci.getAllMethodsParentFirst()) {
-                       if (m.hasAnnotation(RestHook.class) && 
m.getLastAnnotation(RestHook.class).value() == HookEvent.INIT) {
-                               m.setAccessible();
-                               String sig = m.getSignature();
-                               if (! map.containsKey(sig))
-                                       map.put(sig, m);
-                       }
-               }
-               for (MethodInfo m : map.values()) {
-                       List<ParamInfo> params = m.getParams();
-
-                       List<ClassInfo> missing = 
beanStore.getMissingParamTypes(params);
-                       if (!missing.isEmpty())
-                               throw new RestServletException("Could not call 
@RestHook(INIT) method {0}.{1}.  Could not find prerequisites: {2}.", 
m.getDeclaringClass().getSimpleName(), m.getSignature(), 
missing.stream().map(x->x.getSimpleName()).collect(Collectors.joining(",")));
-
-                       try {
-                               m.invoke(resource, beanStore.getParams(params));
-                       } catch (Exception e) {
-                               throw new RestServletException(e, "Exception 
thrown from @RestHook(INIT) method {0}.{1}.", 
m.getDeclaringClass().getSimpleName(), m.getSignature());
-                       }
-               }
-               return this;
+       public final Config config() {
+               return config;
        }
 
        /**
@@ -609,37 +653,65 @@ public class RestContextBuilder extends ContextBuilder 
implements ServletConfig
         * @param config The new config file.
         * @return This object (for method chaining).
         */
+       @FluentSetter
        public RestContextBuilder config(Config config) {
                this.config = config;
                return this;
        }
 
-       
//----------------------------------------------------------------------------------------------------
-       // Methods that give access to the config file, var resolver, and 
properties.
-       
//----------------------------------------------------------------------------------------------------
-
        /**
-        * Returns the external configuration file for this resource.
-        *
-        * <p>
-        * The configuration file location is determined via the {@link 
Rest#config() @Rest(config)}
-        * annotation on the resource.
-        *
-        * <p>
-        * The config file can be programmatically overridden by adding the 
following method to your resource:
-        * <p class='bcode w800'>
-        *      <jk>public</jk> Config createConfig(ServletConfig 
servletConfig) <jk>throws</jk> ServletException;
-        * </p>
-        *
-        * <p>
-        * If a config file is not set up, then an empty config file will be 
returned that is not backed by any file.
+        * Creates the config for this builder.
         *
-        * @return The external config file for this resource.  Never 
<jk>null</jk>.
+        * @param beanStore The bean store to use for creating the config.
+        * @param resourceClass The resource class.
+        * @return A new bean store.
+        * @throws Exception If bean store could not be instantiated.
         */
-       public Config getConfig() {
-               return config;
+       protected Config createConfig(BeanStore beanStore, Class<?> 
resourceClass) throws Exception {
+
+               Value<Config> v = Value.empty();
+
+               // Get implementation from:  public static Config createConfig()
+               beanStore
+                       .beanCreateMethodFinder(Config.class, resourceClass)
+                       .find("createConfig")
+                       .execute()
+                       .ifPresent(x -> v.set(x));
+
+               // Get implementation from bean store.
+               if (v.isEmpty())
+                       beanStore.getBean(Config.class).ifPresent(x -> 
v.set(x));
+
+               // Find our config file.  It's the last non-empty 
@RestResource(config).
+               VarResolver vr = 
beanStore.getBean(VarResolver.class).orElseThrow(()->runtimeException("VarResolver
 not found."));
+               String cf = ClassInfo.of(resourceClass)
+                       .getAnnotations(Rest.class)
+                       .stream()
+                       .map(x -> x.config())
+                       .filter(x -> ! x.isEmpty())
+                       .reduce((x1,x2)->x2)
+                       .map(x -> vr.resolve(x))
+                       .orElse("");
+
+               // If not specified or value is set to SYSTEM_DEFAULT, use 
system default config.
+               if (v.isEmpty() && "SYSTEM_DEFAULT".equals(cf))
+                       v.set(Config.getSystemDefault());
+
+               // Otherwise build one.
+               if (v.isEmpty()) {
+                       ConfigBuilder cb = Config.create().varResolver(vr);
+                       if (! cf.isEmpty())
+                               cb.name(cf);
+                       v.set(cb.build());
+               }
+
+               return v.get();
        }
 
+       
//----------------------------------------------------------------------------------------------------
+       // Methods that give access to the config file, var resolver, and 
properties.
+       
//----------------------------------------------------------------------------------------------------
+
        /**
         * Returns the serializer group builder containing the serializers for 
marshalling POJOs into response bodies.
         *
@@ -939,68 +1011,6 @@ public class RestContextBuilder extends ContextBuilder 
implements ServletConfig
        }
 
        /**
-        * <i><l>RestContext</l> configuration property:&emsp;</i>  Bean store.
-        *
-        * <p>
-        * The resolver used for resolving instances of child resources and 
various other beans including:
-        * <ul>
-        *      <li>{@link RestLogger}
-        *      <li>{@link SwaggerProvider}
-        *      <li>{@link FileFinder}
-        *      <li>{@link StaticFiles}
-        * </ul>
-        *
-        * <p>
-        * Note that the <c>SpringRestServlet</c> classes uses the 
<c>SpringBeanStore</c> class to allow for any
-        * Spring beans to be injected into your REST resources.
-        *
-        * <ul class='seealso'>
-        *      <li class='link'>{@doc RestInjection}
-        * </ul>
-        *
-        * @param value
-        *      The new value for this setting.
-        *      <br>The default is {@link BasicRestLogger}.
-        * @return This object (for method chaining).
-        */
-       @FluentSetter
-       public RestContextBuilder beanStore(Class<? extends BeanStore> value) {
-               beanStoreRef.type(value);
-               return this;
-       }
-
-       /**
-        * <i><l>RestContext</l> configuration property:&emsp;</i>  Bean store.
-        *
-        * <p>
-        * The resolver used for resolving instances of child resources and 
various other beans including:
-        * <ul>
-        *      <li>{@link RestLogger}
-        *      <li>{@link SwaggerProvider}
-        *      <li>{@link FileFinder}
-        *      <li>{@link StaticFiles}
-        * </ul>
-        *
-        * <p>
-        * Note that the <c>Spr÷ingRestServlet</c> classes uses the 
<c>SpringBeanStore</c> class to allow for any
-        * Spring beans to be injected into your REST resources.
-        *
-        * <ul class='seealso'>
-        *      <li class='link'>{@doc RestInjection}
-        * </ul>
-        *
-        * @param value
-        *      The new value for this setting.
-        *      <br>The default is {@link BasicRestLogger}.
-        * @return This object (for method chaining).
-        */
-       @FluentSetter
-       public RestContextBuilder beanStore(BeanStore value) {
-               beanStoreRef.value(value);
-               return this;
-       }
-
-       /**
         * REST call logger.
         *
         * <p>
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
index 12c7225..c2b2d25 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/annotation/RestAnnotation.java
@@ -1072,7 +1072,6 @@ public class RestAnnotation {
                        type(a.staticFiles()).ifPresent(x -> b.staticFiles(x));
                        string(a.path()).ifPresent(x -> b.path(x));
                        string(a.clientVersionHeader()).ifPresent(x -> 
b.clientVersionHeader(x));
-                       type(a.beanStore()).ifPresent(x -> b.beanStore(x));
                        type(a.callLogger()).ifPresent(x -> b.callLogger(x));
                        type(a.swaggerProvider()).ifPresent(x -> 
b.swaggerProvider(x));
                        type(a.restOpContextClass()).ifPresent(x -> 
b.restOpContextClass(x));
diff --git a/juneau-utest/src/test/java/org/apache/juneau/ValueTest.java 
b/juneau-utest/src/test/java/org/apache/juneau/ValueTest.java
index 7c91319..420a3ae 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/ValueTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/ValueTest.java
@@ -15,10 +15,6 @@ package org.apache.juneau;
 import static org.junit.Assert.*;
 import static org.junit.runners.MethodSorters.*;
 
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.apache.juneau.reflect.*;
 import org.junit.*;
 
 @FixMethodOrder(NAME_ASCENDING)
@@ -35,30 +31,4 @@ public class ValueTest {
        public void testSubclass() {
                assertEquals(A1.class, Value.getParameterType(A.class));
        }
-
-       
//-----------------------------------------------------------------------------------------------------------------
-       // Value used in parameter.
-       
//-----------------------------------------------------------------------------------------------------------------
-       public static class B {
-               public void b(Value<B1> b1) {};
-       }
-       public static class B1 {}
-
-       @Test
-       public void testOnParameter() throws Exception {
-               assertEquals(B1.class, 
Value.getParameterType(B.class.getMethod("b", Value.class), 0));
-       }
-
-       
//-----------------------------------------------------------------------------------------------------------------
-       // Value used on parameter of parameterized-type.
-       
//-----------------------------------------------------------------------------------------------------------------
-       public interface C {
-               void m1(Value<List<Integer>> v);
-       }
-
-       @Test
-       public void testOnParameterType() throws Exception {
-               Type t = Value.getParameterType(C.class.getMethod("m1", 
Value.class), 0);
-               assertEquals("List<Integer>", ClassInfo.of(t).getShortName());
-       }
 }

Reply via email to