-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Builder definitions in final Appender implementations unncessarily use Generics on Builder class #3368
Comments
Removing the type variable It is probably OK to do that. @vy, what do you think? |
I would expect there to be more compatibility implications. Nevertheless,
these classes should never be accessed programmatically — that is how we
advise users in docs too. Hence, I am fine with making appender builders
final and removing their type param.
Op ma 6 jan 2025 om 16:12 schreef Piotr P. Karwasz ***@***.***
…
From a coding perspective a trivial change but more of a binary
compatibility problem.
Removing the type variable B should be binary compatible (the erasure of B
is Builder, so the descriptor of the methods remains the same). The only
problem would be adding the final modifier to the Builder class (and
removing the public constructor).
It is probably OK to do that. @vy <https://github.com/vy>, what do you
think?
—
Reply to this email directly, view it on GitHub
<#3368 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAARTSLAK2VIURAKM3LTJY32JKMPBAVCNFSM6AAAAABUVWVDLKVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDKNZTGMYTKMRQGE>
.
You are receiving this because you were mentioned.Message ID:
***@***.***>
|
I am surprised to hear that these should never be accessed programmatically? We have been doing this for years to create dynamic runtime-only appenders and loggers - since Log4j 1.x. Since Log4j 2.x we have a CompositeConfiguration with a nestted custom runtime-configuration for these runtime only service-appenders/loggers. The new Log4j 2.x docs also clearly state "Log4j Core can be configured programmatically too." The warning you are referring to is probably this one: "We strongly advise against programmatically modifying components of a configuration! This section will explain what it is, and why you should avoid it." - but this would not be directly relevant to calling the builder methods. Unfortunately in our case we have an old legacy monolilth which provided admin functions to add/remove/update loggers/appenders - functionality the users don't want to give up :( - and since the Log4j configuration objects cannot be used to recreate an XML file from an existing configuration - we have had to get ... creative. :/ Also the Log4j Plugin concept sort of breaks down in many spots because many other configuration classes are final , have private attributes, or have package-private functionality, (i.e. providing an alternate "BurstFilter" implementation - trivial example). O_o |
similar scenario on
|
The opinions on this matter diverge in the PMC. We agree that the best way to modify a configuration is to create a new one and replace the old one. This prevents subtle bugs like adding an appender to a running configuration without previously starting it. We do not agree, which is the best way to create a new configuration:
The choice is between binary compatibility between major releases and type safety. |
Thanks @ppkarwasz , I don't know how many people are using Log4j via the Builders... For me, wither/setter doesn't matter to me as long as it works (personally I prefer withers in builders - its feels more "builder" than "bean" :P). But yeah from a purist perspective the configuration builders are currently all over the place - withers/setters, sometimes conversion (ie. String -> Level) must happen before calling builder, sometimes not - some filters have "createNewFilter" others use Builders.... I guess I wouldn't be as critical about binary compatibility between major releases - at least not on a non-public API (core) "edge-case" :). But I am (thankfully) not responsibile for a major logging library .D |
@JWT007, why do you have to do that by programmatically accessing the components, directly? If you have the initial, say, XML configuration, you can update the XML with the changed appends/loggers, feed it again to
@ppkarwasz, Configuration Builder API (aka. the glorified DOM builder) is as type-safe as XML/YAML/JSON/Properties configurations files. I don't think type-safety is a tie breaker here. If it would be, we would have seen users asking for a type-safe logging configuration, and we don't. There is life-cycle related magic happening when a component gets realized from a configuration. Programmatically making that happen is walking on a minefield. I think the problem mostly emanates from a disagreement between maintainers on what is the API boundary for Log4j Core. For sure everyone agrees that the configuration file format is one such API – we shouldn't break it. What else? Shall we make In overall, I don't know if Log4j 3, 4, 5, etc. will support |
Hi @vy , as I mentioned, we have a few things going on. Here I will try and provide some rough details but it is not "relevant" to this ticket directly.
I am a big fan of fluent APIs - the ConfigurationBuilder is OK but unwieldy for a lot of content or for dynamic changes. Also, it doesn't really document the behaviour very well in some cases: For example, this will throw NPEs (trying to represent an undefined onResult/onMismatchResult).
...but this will probably not - (but it will put null attrribute values in the backing map - don't know if that causes problems downstream):
Of course, this would be easier if I could take any configuration X and use it to re-generate the XML representation at runtime - but that unfortunately is not possible. |
@JWT007, if I understand you right, you have
You're combining first three into the bootstrap configuration using |
Log4j 2.24
Not technically a bug??? But not a feature-request either...just pointing it out...if no interest in changing this from L4J team go ahead and close it
The appender Builders (ConsoleAppender.Builder, FileAppender.Builder, etc) have been generically defiined.
For example:
This means when not chaining you need to handle the generics:
ConsoleAppender.Builder<?> builder = ConsoleAppender.newBuilder();
This is OK for the abstract Builders that are inherited, but a wee bit non-standard for concrete builder implementations.
Since the appender classes are final one might assume its builders can also be final and don't need the generics on the class itself.
I think it could be simplified::
For example ConsoleAppender:
ConsoleAppender.Builder builder = ConsoleAppender.newBuilder();
From a coding perspective a trivial change but more of a binary compatibility problem.
The text was updated successfully, but these errors were encountered: