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 45428d2 Context API refactoring.
45428d2 is described below
commit 45428d2e21d75b6b54b1d242a35e63824b75c291
Author: JamesBognar <[email protected]>
AuthorDate: Sat Sep 11 12:47:59 2021 -0400
Context API refactoring.
---
.../main/java/org/apache/juneau/cp/BeanStore.java | 14 +++
.../java/org/apache/juneau/rest/RestContext.java | 123 +++++++--------------
.../org/apache/juneau/rest/RestContextBuilder.java | 102 ++++++++++++++++-
3 files changed, 147 insertions(+), 92 deletions(-)
diff --git
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java
index f5836d5..ce41fbc 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
@@ -271,6 +271,20 @@ public class BeanStore {
}
/**
+ * Same as {@link #addBean(Class, Object)} but returns the bean instead
of this object.
+ *
+ * @param <T> The class to associate this bean with.
+ * @param c The class to associate this bean with.
+ * @param t The bean.
+ * @return The bean.
+ */
+ public <T> T add(Class<T> c, T t) {
+ assertCanWrite();
+ addBean(c.getName(), t);
+ return t;
+ }
+
+ /**
* Adds a named bean of the specified type to this factory.
*
* @param <T> The class to associate this bean with.
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 0e15306..7fd0fbe 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
@@ -260,16 +260,15 @@ public class RestContext extends Context {
.addBean(RestContextBuilder.class, builder)
.addBean(AnnotationWorkList.class,
builder.getApplied());
- BeanStore bf = beanStore;
+ BeanStore bs = beanStore;
- Logger l = logger = createLogger(r, builder, bf);
- bf.addBean(Logger.class, l);
+ logger = bs.add(Logger.class, builder.logger());
- ThrownStore ts = thrownStore = createThrownStore(r,
builder, parent, bf);
- bf.addBean(ThrownStore.class, ts);
+ ThrownStore ts = thrownStore = createThrownStore(r,
builder, parent, bs);
+ bs.addBean(ThrownStore.class, ts);
- methodExecStore = createMethodExecStore(r, builder, bf,
ts);
- bf.addBean(MethodExecStore.class, methodExecStore);
+ methodExecStore = createMethodExecStore(r, builder, bs,
ts);
+ bs.addBean(MethodExecStore.class, methodExecStore);
Messages m = messages = createMessages(r, builder);
@@ -277,42 +276,41 @@ public class RestContext extends Context {
.varResolver()
.bean(Messages.class, messages)
.build();
- bf.addBean(VarResolver.class, vr);
+ bs.addBean(VarResolver.class, vr);
- config = builder.config.resolving(vr.createSession());
- bf.addBean(Config.class, config);
+ config = bs.add(Config.class,
builder.config().resolving(vr.createSession()));
- responseProcessors = createResponseProcessors(r,
builder, bf).toArray();
+ responseProcessors = createResponseProcessors(r,
builder, bs).toArray();
callLoggerDefault = builder.callLoggerDefault;
debugDefault = builder.debugDefault;
- callLogger = createCallLogger(r, builder, bf, l, ts);
- bf.addBean(RestLogger.class, callLogger);
+ callLogger = createCallLogger(r, builder, bs, logger,
ts);
+ bs.addBean(RestLogger.class, callLogger);
- partSerializer = createPartSerializer(r, builder, bf);
- bf.addBean(HttpPartSerializer.class, partSerializer);
+ partSerializer = createPartSerializer(r, builder, bs);
+ bs.addBean(HttpPartSerializer.class, partSerializer);
- partParser = createPartParser(r, builder, bf);
- bf.addBean(HttpPartParser.class, partParser);
+ partParser = createPartParser(r, builder, bs);
+ bs.addBean(HttpPartParser.class, partParser);
- jsonSchemaGenerator = createJsonSchemaGenerator(r,
builder, bf);
- bf.addBean(JsonSchemaGenerator.class,
jsonSchemaGenerator);
+ jsonSchemaGenerator = createJsonSchemaGenerator(r,
builder, bs);
+ bs.addBean(JsonSchemaGenerator.class,
jsonSchemaGenerator);
- fileFinder = createFileFinder(r, builder, bf);
- bf.addBean(FileFinder.class, fileFinder);
+ fileFinder = createFileFinder(r, builder, bs);
+ bs.addBean(FileFinder.class, fileFinder);
fileFinderDefault =
builder.fileFinderDefault.value().orElse(fileFinder);
- staticFiles = createStaticFiles(r, builder, bf);
- bf.addBean(StaticFiles.class, staticFiles);
+ staticFiles = createStaticFiles(r, builder, bs);
+ bs.addBean(StaticFiles.class, staticFiles);
staticFilesDefault =
builder.staticFilesDefault.value().orElse(staticFiles);
- defaultRequestHeaders = createDefaultRequestHeaders(r,
builder, bf).build();
- defaultResponseHeaders =
createDefaultResponseHeaders(r, builder, bf).build();
- defaultRequestAttributes =
createDefaultRequestAttributes(r, builder, bf);
+ defaultRequestHeaders = createDefaultRequestHeaders(r,
builder, bs).build();
+ defaultResponseHeaders =
createDefaultResponseHeaders(r, builder, bs).build();
+ defaultRequestAttributes =
createDefaultRequestAttributes(r, builder, bs);
- opArgs = createOpArgs(r, builder, bf).asArray();
- hookMethodArgs = createHookMethodArgs(r, builder,
bf).asArray();
+ opArgs = createOpArgs(r, builder, bs).asArray();
+ hookMethodArgs = createHookMethodArgs(r, builder,
bs).asArray();
uriContext = builder.uriContext;
uriAuthority = builder.uriAuthority;
@@ -328,7 +326,7 @@ public class RestContext extends Context {
defaultCharset = builder.defaultCharset;
maxInput = builder.maxInput;
- debugEnablement = createDebugEnablement(r, builder, bf);
+ debugEnablement = createDebugEnablement(r, builder, bs);
path = ofNullable(builder.path).orElse("");
fullPath = (builder.parentContext == null ? "" :
(builder.parentContext.fullPath + '/')) + path;
@@ -338,16 +336,16 @@ public class RestContext extends Context {
p += "/*";
pathMatcher = UrlPathMatcher.of(p);
- startCallMethods = createStartCallMethods(r, builder,
bf).stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
- endCallMethods = createEndCallMethods(r, builder,
bf).stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
- postInitMethods = createPostInitMethods(r, builder,
bf).stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
- postInitChildFirstMethods =
createPostInitChildFirstMethods(r, builder,
bf).stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
- destroyMethods = createDestroyMethods(r, builder,
bf).stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
+ startCallMethods = createStartCallMethods(r, builder,
bs).stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
+ endCallMethods = createEndCallMethods(r, builder,
bs).stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
+ postInitMethods = createPostInitMethods(r, builder,
bs).stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
+ postInitChildFirstMethods =
createPostInitChildFirstMethods(r, builder,
bs).stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
+ destroyMethods = createDestroyMethods(r, builder,
bs).stream().map(this::toMethodInvoker).toArray(MethodInvoker[]::new);
- preCallMethods = createPreCallMethods(r, builder,
bf).stream().map(this::toRestOpInvoker).toArray(RestOpInvoker[]:: new);
- postCallMethods = createPostCallMethods(r, builder,
bf).stream().map(this::toRestOpInvoker).toArray(RestOpInvoker[]:: new);
+ preCallMethods = createPreCallMethods(r, builder,
bs).stream().map(this::toRestOpInvoker).toArray(RestOpInvoker[]:: new);
+ postCallMethods = createPostCallMethods(r, builder,
bs).stream().map(this::toRestOpInvoker).toArray(RestOpInvoker[]:: new);
- restOperations = createRestOperations(r, builder, bf);
+ restOperations = createRestOperations(r, builder, bs);
List<RestOpContext> opContexts =
restOperations.getOpContexts();
@@ -367,9 +365,9 @@ public class RestContext extends Context {
consumes = AList.unmodifiable(s);
}
- restChildren = createRestChildren(r, builder, bf,
builder.inner);
+ restChildren = createRestChildren(r, builder, bs,
builder.inner);
- swaggerProvider = createSwaggerProvider(r, builder, bf,
fileFinder, m, vr);
+ swaggerProvider = createSwaggerProvider(r, builder, bs,
fileFinder, m, vr);
} catch (BasicHttpException e) {
_initException = e;
@@ -684,7 +682,6 @@ public class RestContext extends Context {
* <br>Created by {@link RestContextBuilder#beanStore()}.
* @param logger
* The Java logger to use for logging messages.
- * <br>Created by {@link
#createLogger(Object,RestContextBuilder,BeanStore)}.
* @param thrownStore
* The thrown exception statistics store.
* <br>Created by {@link
#createThrownStore(Object,RestContextBuilder,RestContext,BeanStore)}.
@@ -736,7 +733,6 @@ public class RestContext extends Context {
* <br>Created by {@link RestContextBuilder#beanStore()}.
* @param logger
* The Java logger to use for logging messages.
- * <br>Created by {@link
#createLogger(Object,RestContextBuilder,BeanStore)}.
* @param thrownStore
* The thrown exception statistics store.
* <br>Created by {@link
#createThrownStore(Object,RestContextBuilder,RestContext,BeanStore)}.
@@ -1029,51 +1025,6 @@ public class RestContext extends Context {
}
/**
- * Instantiates logger for this REST resource.
- *
- * <p>
- * Instantiates based on the following logic:
- * <ul>
- * <li>Looks for a static or non-static <c>createLogger()</>
method that returns <c>{@link Logger}</c> on the
- * resource class with any of the following arguments:
- * <ul>
- * <li>{@link RestContext}
- * <li>{@link BeanStore}
- * <li>Any {@doc RestInjection injected beans}.
- * </ul>
- * <li>Resolves it via the bean store registered in this context.
- * <li>Instantiates via
<c>Logger.<jsm>getLogger</jsm>(<jv>resource</jv>.getClass().getName())</c>.
- * </ul>
- *
- * @param resource
- * The REST servlet or bean that this context defines.
- * @param builder
- * The builder for this object.
- * @param beanStore
- * The factory used for creating beans and retrieving injected
beans.
- * <br>Created by {@link RestContextBuilder#beanStore()}.
- * @return The logger for this REST resource.
- * @throws Exception If logger could not be instantiated.
- */
- protected Logger createLogger(Object resource, RestContextBuilder
builder, BeanStore beanStore) throws Exception {
-
- Logger x = beanStore.getBean(Logger.class).orElse(null);
-
- if (x == null)
- x = Logger.getLogger(className(resource));
-
- x = BeanStore
- .of(beanStore, resource)
- .addBean(Logger.class, x)
- .beanCreateMethodFinder(Logger.class, resource)
- .find("createLogger")
- .withDefault(x)
- .run();
-
- return x;
- }
-
- /**
* Instantiates the JSON schema generator for this REST resource.
*
* <p>
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 255dd61..59090a0 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
@@ -14,6 +14,7 @@ package org.apache.juneau.rest;
import static org.apache.juneau.assertions.Assertions.*;
import static org.apache.juneau.http.HttpHeaders.*;
+import static org.apache.juneau.internal.ClassUtils.*;
import static org.apache.juneau.internal.ExceptionUtils.*;
import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.parser.Parser.*;
@@ -27,6 +28,7 @@ import java.lang.reflect.Method;
import java.nio.charset.*;
import java.util.*;
import java.util.function.*;
+import java.util.logging.*;
import java.util.stream.*;
import javax.servlet.*;
@@ -117,8 +119,10 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
Supplier<?> resource;
ServletContext servletContext;
- Config config;
+ private Config config;
private VarResolver.Builder varResolver;
+ private Logger logger;
+
String
allowedHeaderParams = env("RestContext.allowedHeaderParams",
"Accept,Content-Type"),
allowedMethodHeaders = env("RestContext.allowedMethodHeaders",
""),
@@ -309,9 +313,25 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
public RestContextBuilder init(Object resource) throws ServletException
{
this.resource = resource instanceof Supplier ?
(Supplier<?>)resource : ()->resource;
- ClassInfo rci = ClassInfo.ofProxy(resource);
BeanStore bs = beanStore();
+ runInitHooks(bs, resource());
+ logger();
+
+ return this;
+ }
+
+ private Supplier<?> resource() {
+ if (resource == null)
+ throw runtimeException("Resource not available.
init(Object) has not been called.");
+ return resource;
+ }
+
+ private void runInitHooks(BeanStore beanStore, Supplier<?> resource)
throws ServletException {
+
+ Object r = resource.get();
+ ClassInfo rci = ClassInfo.ofProxy(r);
+
Map<String,MethodInfo> map = new LinkedHashMap<>();
for (MethodInfo m : rci.getAllMethodsParentFirst()) {
if (m.hasAnnotation(RestHook.class) &&
m.getLastAnnotation(RestHook.class).value() == HookEvent.INIT) {
@@ -321,20 +341,20 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
map.put(sig, m);
}
}
+
for (MethodInfo m : map.values()) {
List<ParamInfo> params = m.getParams();
- List<ClassInfo> missing =
bs.getMissingParamTypes(params);
- if (!missing.isEmpty())
+ 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, bs.getParams(params));
+ m.invoke(r, 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;
}
/**
@@ -708,6 +728,76 @@ public class RestContextBuilder extends ContextBuilder
implements ServletConfig
return v.get();
}
+ /**
+ * Returns the logger to use for the REST resource.
+ *
+ * @return The logger to use for the REST resource.
+ * @throws RuntimeException If {@link #init(Object)} has not been
called.
+ */
+ public final Logger logger() {
+ if (logger == null)
+ logger = createLogger(beanStore(), resource());
+ return logger;
+ }
+
+ /**
+ * Sets the logger to use for the REST resource.
+ *
+ * <p>
+ * If not specified, the logger used is created by {@link
#createLogger(BeanStore, Supplier)}.
+ *
+ * @param value The logger to use for the REST resource.
+ * @return This object.
+ */
+ public final RestContextBuilder logger(Logger value) {
+ logger = value;
+ return this;
+ }
+
+ /**
+ * Instantiates logger for this REST resource.
+ *
+ * <p>
+ * Instantiates based on the following logic:
+ * <ul>
+ * <li>Looks for a static or non-static <c>createLogger()</>
method that returns <c>{@link Logger}</c> on the
+ * resource class with any of the following arguments:
+ * <ul>
+ * <li>{@link RestContext}
+ * <li>{@link BeanStore}
+ * <li>Any {@doc RestInjection injected beans}.
+ * </ul>
+ * <li>Resolves it via the bean store registered in this context.
+ * <li>Instantiates via
<c>Logger.<jsm>getLogger</jsm>(<jv>resource</jv>.getClass().getName())</c>.
+ * </ul>
+ *
+ * @param resource
+ * The REST servlet or bean that this context defines.
+ * @param beanStore
+ * The factory used for creating beans and retrieving injected
beans.
+ * <br>Created by {@link RestContextBuilder#beanStore()}.
+ * @return The logger for this REST resource.
+ */
+ protected Logger createLogger(BeanStore beanStore, Supplier<?>
resource) {
+
+ Value<Logger> v = Value.empty();
+
+ beanStore.getBean(Logger.class).ifPresent(x -> v.set(x));
+
+ if (v.isEmpty())
+ v.set(Logger.getLogger(className(resource.get())));
+
+ BeanStore
+ .of(beanStore, resource.get())
+ .addBean(Logger.class, v.get())
+ .beanCreateMethodFinder(Logger.class, resource)
+ .find("createLogger")
+ .execute()
+ .ifPresent(x -> v.set(x));
+
+ return v.get();
+ }
+
//----------------------------------------------------------------------------------------------------
// Methods that give access to the config file, var resolver, and
properties.
//----------------------------------------------------------------------------------------------------