Skip to content

fix: add SLF4J NOP binding to target, clean up stale imports#1280

Draft
joaodinissf wants to merge 1 commit intodsldevkit:masterfrom
joaodinissf:fix/slf4j-missing-binding
Draft

fix: add SLF4J NOP binding to target, clean up stale imports#1280
joaodinissf wants to merge 1 commit intodsldevkit:masterfrom
joaodinissf:fix/slf4j-missing-binding

Conversation

@joaodinissf
Copy link
Copy Markdown
Collaborator

@joaodinissf joaodinissf commented Mar 3, 2026

What

Add slf4j.nop 2.0.17 to the DDK target platform (from the Eclipse Orbit aggregation repository already used for other dependencies).

Also removes unused Import-Package: org.slf4j from 3 test bundle manifests where no source file references org.slf4j:

  • com.avaloq.tools.ddk.check.ui.test
  • com.avaloq.tools.ddk.xtext.test
  • com.avaloq.tools.ddk.xtext.test.core

Retains org.slf4j in com.avaloq.tools.ddk.test.ui — its SwtBot wrapper classes directly use org.slf4j.Logger.

Why

The SLF4J NOP binding should be available to the OSGi runtime. However, due to classloader isolation in OSGi, the startup warning (SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder" on 1.7.x or SLF4J(W): No SLF4J providers were found on 2.x) cannot be fully suppressed — slf4j.nop is a standalone bundle, not a fragment of slf4j.api, so ServiceLoader-based provider discovery does not find it before SLF4J's first initialization. This is a known limitation shared by Eclipse Platform itself.

References

rubenporras
rubenporras previously approved these changes Mar 4, 2026
@rubenporras
Copy link
Copy Markdown
Member

@KrisLimbo , can you check this does not introduce again the warning in the builds of our other project?

@joaodinissf joaodinissf changed the title fix: add SLF4J NOP binding to suppress StaticLoggerBinder warning fix: remove dead SLF4J imports, add NOP binding to target Mar 4, 2026
@joaodinissf joaodinissf force-pushed the fix/slf4j-missing-binding branch from 3ca0f0e to ea0f764 Compare March 4, 2026 20:01
@joaodinissf joaodinissf changed the title fix: remove dead SLF4J imports, add NOP binding to target fix: add SLF4J NOP binding to target, clean up stale imports Mar 4, 2026
@joaodinissf joaodinissf force-pushed the fix/slf4j-missing-binding branch from ea0f764 to fe53424 Compare March 4, 2026 20:18
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde version="3.8"?>
<target name="DDK Target" sequenceNumber="25">
<locations>
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you keep the line endings of this file?

Copy link
Copy Markdown
Collaborator Author

@joaodinissf joaodinissf Mar 5, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a formatting fix, not line endings. But happy to do it separately.
I likely won't have enough bandwidth to finish this today, but I'll get to it as soon as I get a chance.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized yesterday evening we may want to do this slightly differently. I'll convert this to draft for now, and move to ready once you can have a look.

@joaodinissf joaodinissf marked this pull request as draft March 5, 2026 08:40
@joaodinissf joaodinissf force-pushed the fix/slf4j-missing-binding branch from fe53424 to 607b20f Compare April 1, 2026 19:10
@joaodinissf joaodinissf marked this pull request as ready for review April 1, 2026 19:17
@joaodinissf joaodinissf force-pushed the fix/slf4j-missing-binding branch 4 times, most recently from 5c66da9 to c8067bb Compare April 1, 2026 20:34
Add slf4j.nop 2.0.17 from Eclipse Orbit aggregation 4.39.0 to the DDK
target platform. This makes the SLF4J NOP binding available to the OSGi
runtime, though due to classloader isolation in OSGi the startup warning
cannot be fully suppressed — slf4j.nop is a standalone bundle (not a
fragment of slf4j.api), so ServiceLoader-based provider discovery does
not find it before SLF4J's first initialization. This is a known
limitation shared by Eclipse Platform itself.

References:
- qos-ch/slf4j#427
- https://github.com/orgs/eclipse-orbit/discussions/24

Also removes unused Import-Package: org.slf4j from three test bundle
manifests where no source file references org.slf4j:
- com.avaloq.tools.ddk.check.ui.test
- com.avaloq.tools.ddk.xtext.test
- com.avaloq.tools.ddk.xtext.test.core

Retains org.slf4j in com.avaloq.tools.ddk.test.ui — its SwtBot wrapper
classes directly use org.slf4j.Logger.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@joaodinissf joaodinissf force-pushed the fix/slf4j-missing-binding branch from c8067bb to f086983 Compare April 1, 2026 23:17
@joaodinissf
Copy link
Copy Markdown
Collaborator Author

Investigation: SLF4J warning in OSGi — Claude Code analysis

Background

This PR adds slf4j.nop 2.0.17 to the target platform. While the build passes, a runtime warning persists during Tycho Surefire test execution:

SLF4J(W): No SLF4J providers were found.
SLF4J(W): Defaulting to no-operation (NOP) logger implementation

(On current master, the equivalent warning is SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder" — the 1.7.x variant.)

Root cause

SLF4J 2.x discovers providers via java.util.ServiceLoader. In OSGi, each bundle has its own classloader, so slf4j.api's classloader cannot see META-INF/services/org.slf4j.spi.SLF4JServiceProvider inside the separate slf4j.nop bundle. This is confirmed by the SLF4J maintainers in qos-ch/slf4j#427.

What was tried

  1. SPI Fly (OSGi Service Loader Mediator): Configured bundleStartLevel in tycho-surefire-plugin with org.apache.aries.spifly.dynamic.bundle at level 2 and slf4j.nop at level 4. The provider did register successfully:

    INFO: Registered provider org.slf4j.nop.NOPServiceProvider of service org.slf4j.spi.SLF4JServiceProvider in bundle slf4j.nop
    

    However, the warning still appears because SLF4J's first LoggerFactory.getLogger() call fires before SPI Fly finishes its scan — a startup ordering race.

  2. -Dslf4j.provider system property: Does not work in OSGi because Class.forName() uses slf4j.api's classloader, which can't reach slf4j.nop.

Why this can't be fully fixed

The only way to fully suppress the warning would be packaging slf4j.nop as a fragment of slf4j.api (shared classloader, no ServiceLoader needed). This is an upstream Eclipse Orbit packaging decision — slf4j.nop is currently packaged as a standalone bundle.

Eclipse Platform itself has the same limitation. Their approach (eclipse-platform/eclipse.platform.releng.aggregator#1094) configures start levels in .product files, which only applies to Eclipse RCP products, not plugin test suites like ours.

Decision

The SPI Fly config was removed from this PR since it adds complexity without suppressing the warning. The pragmatic approach is to keep slf4j.nop in the target platform (making the binding available) and accept the harmless startup warning — the same trade-off Eclipse Platform makes.

References


🤖 Investigation performed with Claude Code

@joaodinissf
Copy link
Copy Markdown
Collaborator Author

Follow-up: downstream product configuration

Since DDK plugins are assembled into an Eclipse RCP application downstream, the .product file approach used by Eclipse Platform is viable for the running product. The downstream product's .product file (Configuration tab) should add:

<plugin id="org.apache.aries.spifly.dynamic.bundle" autoStart="true" startLevel="2" />
<plugin id="slf4j.nop" autoStart="true" startLevel="2" />

This ensures SPI Fly (the OSGi Service Loader Mediator) starts early enough to wire slf4j.nop's NOPServiceProvider before SLF4J initializes, fully suppressing the warning in the running product.

The warning that remains in CI is specific to Tycho Surefire's test runtime, which spins up its own Equinox instance without a .product file. For that context, bundleStartLevel in pom.xml is the right mechanism — we verified the provider registers successfully, though a one-time startup race warning persists.


🤖 Claude Code

@joaodinissf
Copy link
Copy Markdown
Collaborator Author

Alternative: suppress warning via SLF4J system property

PR #1299 (stacked on this one) adds -Dslf4j.internal.verbosity=ERROR to the Tycho Surefire test argLine, which suppresses the cosmetic "No SLF4J providers were found" warning using SLF4J's official internal reporting mechanism (available since 2.0.10).

This is a pragmatic complement to the target platform change in this PR. For downstream RCP products, the proper fix remains configuring SPI Fly + slf4j.nop start levels in the .product file — see #1299 description for details.


🤖 Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants