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<Foo> foo) {...}
- * }
- * </p>
- * <p class='bcode w800'>
- * Class<?> 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<BeanStore> <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}<{@link BeanStore}></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: </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: </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());
- }
}