Hi everyone,

As part of the 2022-06 release, the SWTBot project will do a major release
of version 4.0.0. In this version, SWTBot has removed its use of
org.apache.log4j and is instead using the org.slf4j.api facade for its
logging. See Bug 578065 for this change.

I am trying to adapt project Trace Compass to this change and I am having
some issues, perhaps someone can help and/or this information will be
useful to others.

Trace Compass was using the log4j Logger for its SWTBot tests, both to add
its own messages and to rely on SWTBot's log4j debug messages.

The first issue when switching to SWTBot 4.0.0 is that the SWTBot update
site no longer contains org.apache.log4j. So I first tried to change our
target files to add org.apache.log4j from the Orbit update site. I also had
to add an Import-Package dependency to org.slf4j in our swtbot.tests
plug-ins MANIFEST.MF, to avoid 'missing ... indirectly referenced from
.class files' errors, due to it now being used by SWTBot classes.

While the build was now successful, there was no debug logging from the
SWTBot components because there was no slf4j binding installed. The console
would show:

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation

At this point, needing a quick fix, I changed our target files to use the
previous SWTBot release update site (3.1.0) that still uses
org.apache.log4j, instead of using the latest snapshot (4.0.0) update site.

So, now I am trying to do a proper migration to SLF4J.

I updated our targets to use the SWTBot 4.0.0 snapshot and added
org.slf4j.api Import-Package dependency to the swtbot.tests plug-ins
MANIFEST.MF. I removed all use of org.apache.log4j.Logger in our test code
and replaced it with getting a logger from the org.slf4j.LoggerFactory.

Of course there was no logging when running the tests because there was no
binding installed.

~~~ org.slf4j.binding.simple ~~~

I first tried to add org.slf4j.binding.simple from Orbit to our targets.

In my JUnit Plug-In Test Debug Configuration I can see that org.slf4j.api
and org.slf4j.binding.simple plug-ins are added. When I ran the test it did
not log anything because the default log level was INFO.

So I added this line as static initializer in my test code:

System.setProperty("org.slf4j.simpleLogger.log.org.eclipse", "debug");

This works because it covers both our test code classes
org.eclipse.tracecompass.* and the SWTBot classes org.eclipse.swtbot.*. But
it's a bit clunky, and I wanted to configure other settings, like setting
the log file to System.out instead of System.err.

I tried creating a simplelogger.properties file in my test plug-in, adding
it to the Binary Build in the Build Configuration tab and adding it's
location to the Classpath in the Runtime tab.

But when I run the test, the SimpleLoggerConfiguration code tries to load
the properties file from:
Thread.currentThread().getContextClassLoader() (java.lang)
The current thread is PluginTestRunner.
This returns a ContextFinder (org.eclipse.osgi)
But the ContextFinder.basicFindClassLoaders() implementation returns the
first in the list that is a Bundle class loader, and that's the one at
index [5] which is for org.slf4j.api bundle. So it never gets to index [19]
which is our tmf.ui.swtbot.tests bundle that has the
simplelogger.properties resource.

So it doesn't find our test plug-in's simplelogger.properties file and I
can't configure the logger.

I don't really understand how class loaders work so at this point I gave up
on SimpleLogger.

~~~ org.slf4j.binding.log4j12 ~~~

I secondly tried to add org.slf4j.binding.log4j12 from Orbit to our targets.

In my JUnit Plug-In Test Debug Configuration I can see that org.slf4j.api
and org.slf4j.binding.log4j12 plug-ins are added.

But org.slf4j.binding.log4j12 requires org.apache.log4j package and this is
found in org.slf4j.log4j, so this plug-in also needs to be added.

And now when I run my test, the org.apache.log4j.Log4jLoggerFactory static
initializer checks that there is no org.slf4j.impl.Log4jLoggerFactory
loaded, and since there is, it throws the following exception and aborts
the test:

SLF4J: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on
the class path, preempting StackOverflowError.
SLF4J: See also http://www.slf4j.org/codes.html#log4jDelegationLoop for
more details.
Exception in thread "Plug-in Tests Runner"
java.lang.ExceptionInInitializerError
at org.slf4j.impl.StaticLoggerBinder.<init>(StaticLoggerBinder.java:72)
Caused by: java.lang.IllegalStateException
at org.slf4j.impl.Log4jLoggerFactory.<clinit>(Log4jLoggerFactory.java:54)

It seems they are both mutually exclusive but I'm confused because
org.apache.log4j is required by org.slf4j.binding.log4j12 ?!

~~~

So at this point I realize that I don't know what I'm doing wrong, and/or I
don't know what I'm doing. Help?

I would like to figure this out so that we can help other projects that
need to do a similar migration when they switch to SWTBot 4.0.0 after the
upcoming release.

Thanks,

Patrick
SWTBot lead & Trace Compass committer
_______________________________________________
swtbot-dev mailing list
swtbot-dev@eclipse.org
To unsubscribe from this list, visit 
https://www.eclipse.org/mailman/listinfo/swtbot-dev

Reply via email to