Skip to content

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

Merged
merged 8 commits into from
Jan 2, 2024
Merged

Conversation

jvz
Copy link
Member

@jvz jvz commented Jan 2, 2024

  • 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.
  • Various test updates to make use of said test extension updates.
  • Some nullability updates that got pulled in from my changes in spi-updates.

jvz added 2 commits January 1, 2024 23:22
- `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]>
@jvz jvz added api Affects the public API plugins Affects the plugin system labels Jan 2, 2024
@jvz jvz added this to the 3.0.0 milestone Jan 2, 2024
@jvz jvz requested a review from ppkarwasz January 2, 2024 05:34
@jvz jvz self-assigned this Jan 2, 2024
@jvz jvz linked an issue Jan 2, 2024 that may be closed by this pull request
/**
* Toggles Log4j1 configuration file compatibility mode for XML and properties files.
*/
boolean v1config() default false;
Copy link
Member Author

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;
Copy link
Member Author

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;
Copy link
Member Author

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)
Copy link
Member Author

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)
Copy link
Member Author

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.

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())) {
Copy link
Member Author

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);
Copy link
Member Author

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 {
Copy link
Member Author

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.

Copy link
Contributor

@ppkarwasz ppkarwasz left a 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.


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);
Copy link
Contributor

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.

Copy link
Member Author

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?

@jvz
Copy link
Member Author

jvz commented Jan 2, 2024

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).

/**
* Handles parameter resolution of a {@link LoggerContext}.
*/
class LoggerContextResolver extends TypeBasedParameterResolver<LoggerContext> {
Copy link
Member Author

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();
Copy link
Member Author

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.

@jvz jvz merged commit c72576d into apache:main Jan 2, 2024
@jvz jvz deleted the issue-2147 branch January 2, 2024 19:48
@ppkarwasz ppkarwasz modified the milestones: 3.0.0, 3.0.0-beta2 Feb 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api Affects the public API plugins Affects the plugin system
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Update DI system with DSL for configuring bindings
2 participants