-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Update DI system with DSL for configuring bindings #2148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Signed-off-by: Matt Sicker <[email protected]>
- `DI.FactoryBuilder` and related builder classes for configuring a `ConfigurableInstanceFactory`. - Repeatable `@TestBinding` test annotation for specifying simple bindings in tests. - `@LegacyLoggerContextSource` test annotation for specifying v1-style configuration files. - Test extension updates to improve compatibility of different annotations. Related to apache#2147 Signed-off-by: Matt Sicker <[email protected]>
log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/Log4jExtension.java
Show resolved
Hide resolved
/** | ||
* Toggles Log4j1 configuration file compatibility mode for XML and properties files. | ||
*/ | ||
boolean v1config() default false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extracted to new annotation.
/** | ||
* Determines whether to bootstrap a fresh LoggerContextFactory. | ||
*/ | ||
boolean bootstrap() default false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No longer relevant; we just bootstrap them all the time depending on where the annotation is used.
* Overrides the {@link ContextSelector} to use by default. If unset, the test instance can still | ||
* define a context selector factory to override the default {@link ClassLoaderContextSelector}. | ||
*/ | ||
Class<? extends ContextSelector> selector() default ContextSelector.class; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extracted to a new annotation.
public void testSpecifySystemClockShort() { | ||
DI.initializeFactory(instanceFactory); | ||
assertThat(instanceFactory.getInstance(Clock.class)).isInstanceOf(SystemClock.class); | ||
final Clock clock = builder.addInitialBindingFrom(Clock.KEY) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test updates are also related to #1977.
import org.apache.logging.log4j.status.StatusLogger; | ||
import org.junit.jupiter.api.Test; | ||
|
||
@TestBinding(api = ShutdownCallbackRegistry.class, implementation = ShutdownCallbackRegistryTest.Registry.class) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since all test bindings are registered as initial bindings in the new DSL, that helps avoid the need for the old bootstrap
boolean flag in @LoggerContextSource
.
log4j-core/src/main/java/org/apache/logging/log4j/core/LoggerContext.java
Show resolved
Hide resolved
processConditionals(rootNode); | ||
preConfigure(rootNode); | ||
configurationScheduler.start(); | ||
if (rootNode.hasChildren() && rootNode.getChildren().get(0).getName().equalsIgnoreCase("Properties")) { | ||
if (rootNode.hasChildren() | ||
&& "Properties".equalsIgnoreCase(rootNode.getChildren().get(0).getName())) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Various flipping around is from nullability analysis from some time where Node::getName
is technically nullable.
final Level level = Level.valueOf(levelName); | ||
rootLoggerConfig.setLevel(level != null ? level : defaultLevel); | ||
final String defaultLevelName = contextProperties.getStringProperty(Log4jPropertyKey.CONFIG_DEFAULT_LEVEL); | ||
final Level defaultLevel = Level.toLevel(defaultLevelName, Level.ERROR); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also noticed from nullability analysis that calling Level::valueOf
was incorrect here as it couldn't return null
.
return new FactoryBuilder(); | ||
} | ||
|
||
public static class FactoryBuilder { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file is where a lot of the interesting changes are.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In general this looks good to me.
I am only concerned with DI changes so late in the 3.x
lifecycle. As far as know the DI
system is mostly unreviewed/unknown (i.e. except you, no other committer can really say he knows the code). After this PR, can we stabilize it so that people can catch up?
Regarding the nullability annotations, I think this merits a thread on dev@logging
. If all committers are not onboard, it is useless to add them.
log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/Log4jExtension.java
Show resolved
Hide resolved
|
||
class Log4jExtension implements BeforeAllCallback, BeforeEachCallback, AfterEachCallback { | ||
private static final String FQCN = Log4jExtension.class.getName(); | ||
private static final ExtensionContext.Namespace NAMESPACE = ExtensionContext.Namespace.create(Log4jExtension.class); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We could use a single Namepace
for all our extensions. There is one in ExtensionContextAnchor
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I was wondering what you'd think about that. I had originally used ExtensionContextAnchor
directly here, but it works with its own namespace, too. Seems like something we can normalize?
log4j-core-test/src/main/java/org/apache/logging/log4j/core/test/junit/TestBindings.java
Outdated
Show resolved
Hide resolved
The "late" DI changes are being made now based because I wasn't trying to indefinitely delay pre-3.0.0 releases. In the lead up to 2.0.0, we accepted API changes up until 2.0.0 was cut (2.0 technically). |
This ensures that when multiple test methods define test bindings, said bindings do not clobber one another.
/** | ||
* Handles parameter resolution of a {@link LoggerContext}. | ||
*/ | ||
class LoggerContextResolver extends TypeBasedParameterResolver<LoggerContext> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since all these ParameterResolver
extensions are package-private and only used by this particular file, I combined them all into one file. Less lines wasted on license headers 😂
/** | ||
* Specifies the {@linkplain org.apache.logging.log4j.plugins.di.Key#forClass(Class) class to use as a key} for this binding. | ||
*/ | ||
Class<?> api(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will note that some sort of annotation-specific way of specifying a Key
here would also be useful, but I haven't had a need for that particular syntax yet as all the bindings needed in tests from this annotation use plain interfaces as the key rather than any particular namespace, name, qualifier, etc.
DI.FactoryBuilder
and related builder classes for configuring aConfigurableInstanceFactory
.@TestBinding
test annotation for specifying simple bindings in tests.@LegacyLoggerContextSource
test annotation for specifying v1-style configuration files.