Closed kazurayam closed 9 months ago
In the selenium-webdriver-junit4/build.gradle
file, the Selenium Java v4.14.1 (=the current latest) was used.
Just tentatively, I tried to downgrade to v4.13.0:
//seleniumVersion = "4.14.1"
seleniumVersion = "4.13.0"
And runt the test again
Starting Gradle Daemon...
Gradle Daemon started in 1 s 734 ms
> Task :selenium-webdriver-junit4:compileJava UP-TO-DATE
> Task :selenium-webdriver-junit4:processResources UP-TO-DATE
> Task :selenium-webdriver-junit4:classes UP-TO-DATE
> Task :selenium-webdriver-junit4:compileTestJava
> Task :selenium-webdriver-junit4:processTestResources UP-TO-DATE
> Task :selenium-webdriver-junit4:testClasses
2023-10-21 18:44:52 [Test worker] DEBUG i.g.bonigarcia.wdm.WebDriverManager.<init>(225) - Using WebDriverManager 5.5.3
2023-10-21 18:44:53 [Test worker] DEBUG i.g.b.wdm.cache.ResolutionCache.checkValidity(156) - Removing resolution chrome=118 from cache (expired on Sat Oct 21 18:33:34 JST 2023)
2023-10-21 18:44:54 [Test worker] DEBUG i.g.b.wdm.versions.VersionDetector.getBrowserVersionFromTheShell(259) - Detecting chrome version using online commands.properties
2023-10-21 18:44:54 [Test worker] DEBUG i.g.bonigarcia.wdm.versions.Shell.runAndWaitArray(65) - Running command on the shell: [/Applications/Google Chrome.app/Contents/MacOS/Google Chrome, --version]
2023-10-21 18:44:54 [Test worker] DEBUG i.g.bonigarcia.wdm.versions.Shell.runAndWaitArray(69) - Result: Google Chrome 118.0.5993.96
2023-10-21 18:44:54 [Test worker] DEBUG i.g.b.wdm.cache.ResolutionCache.checkKeyInResolutionCache(186) - Resolution chrome118=118.0.5993.70 in cache (valid until 21:03:28 21/10/2023 JST)
2023-10-21 18:44:54 [Test worker] INFO i.g.bonigarcia.wdm.WebDriverManager.resolveDriverVersion(1217) - Using chromedriver 118.0.5993.70 (resolved driver for Chrome 118)
2023-10-21 18:44:54 [Test worker] DEBUG i.g.b.wdm.cache.ResolutionCache.putValueInResolutionCacheIfEmpty(119) - Storing resolution chrome=118 in cache (valid until 19:44:54 21/10/2023 JST)
2023-10-21 18:44:54 [Test worker] DEBUG i.g.bonigarcia.wdm.WebDriverManager.manage(1172) - Driver chromedriver 118.0.5993.70 found in cache
2023-10-21 18:44:54 [Test worker] INFO i.g.bonigarcia.wdm.WebDriverManager.exportDriver(1270) - Exporting webdriver.chrome.driver as /Users/kazuakiurayama/.cache/selenium/chromedriver/mac64/118.0.5993.70/chromedriver
Oct 21, 2023 6:45:05 PM org.openqa.selenium.devtools.CdpVersionFinder findNearestMatch
WARNING: Unable to find an exact match for CDP version 118, so returning the closest version found: 117
2023-10-21 18:45:08 [Test worker] DEBUG i.g.b.w.j.c.h.HelloWorldChromeJUnit4Test.test(60) - The title of https://bonigarcia.dev/selenium-webdriver-java/ is Hands-On Selenium WebDriver with Java
2023-10-21 18:45:08 [AsyncHttpClient-1-4] WARN o.a.netty.handler.WebSocketHandler.handleException(142) - onError
java.net.SocketException: Connection reset
at java.base/sun.nio.ch.SocketChannelImpl.throwConnectionReset(SocketChannelImpl.java:394)
at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:426)
at io.netty.buffer.PooledByteBuf.setBytes(PooledByteBuf.java:254)
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132)
at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:357)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:151)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:833)
Oct 21, 2023 6:45:08 PM org.openqa.selenium.remote.http.WebSocket$Listener onError
WARNING: Connection reset
java.net.SocketException: Connection reset
at java.base/sun.nio.ch.SocketChannelImpl.throwConnectionReset(SocketChannelImpl.java:394)
at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:426)
at io.netty.buffer.PooledByteBuf.setBytes(PooledByteBuf.java:254)
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132)
at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:357)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:151)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:997)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:833)
> Task :selenium-webdriver-junit4:test
io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test > test PASSED
Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0.
You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins.
For more on this, please refer to https://docs.gradle.org/8.4/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation.
BUILD SUCCESSFUL in 43s
5 actionable tasks: 2 executed, 3 up-to-date
18:45:09: Execution finished ':selenium-webdriver-junit4:test --tests "io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test"'.
The HelloWorldChromeJUnit4Test
ran. It failed with strange errors, but I could workaround the java.lang.NoClassDefFoundError: org/openqa/selenium/remote/http/netty/NettyClient$Factory
This implies that the java.lang.NoClassDefFoundError: org/openqa/selenium/remote/http/netty/NettyClient$Factory
is caused by the version 4.14.x of selenium-java
library.
I want to find a way to use the selenium-java v4.14.1 and onward. But how? --- this is the problem I should focus.
I should compare the jar files of selenium-java v4.13.0 and v4.14.1.
org/openqa/selenium/remote/http/netty/NettyClient
class is found in the v4.13.0.org/openqa/selenium/remote/http/netty/NettyClient
class is NOT found in the v4.14.1.Then think what should I do? How should I modify the source of the selenium-webdriver-java project?
https://www.selenium.dev/downloads/ has a link to the "Previous Releases"
I downloaded the selenium-java-4.14.1.zip
:
And I downloaded the selenium-java-4.13.0.zip
as well.
The selenium-java-4.13.0.zip
file contained a jar selenium-remote-driver-4.13.0-sources.jar
. Inside the jar, I could find the org.openqa.selenium.reqmote.http.netty.NettyClient
class, as follows:
The selenium-java-4.13.0.zip
file contained a jar selenium-remote-driver-4.13.0-sources.jar
. Inside the jar, I coud NOT find the org.openqa.selenium.reqmote.http.netty.NettyClient
class. Instead, I found a new class org.openqa.selenium.remote.http.jdk.JdkHttpClient
It seems that the org.openqa.selenium.reqmote.http.netty.NettyClient
class in v4.13.0 was replaced with the org.openqa.selenium.remote.http.jdk.JdkHttpClient
in v4.14.x.
But why? I want to know the reason. I want to read some article that explains the background of the change. I searched and found the following article:
Why does Selenium want to move to Java 11+ HTTP Client?
While AsyncHttpClient provides the required functionality, the open-source project is not been actively maintained since June 2021. It coincides with the fact that Java 11+ provides a built-in HTTP and WebSocket client. Selenium can utilize it to replace AsyncHttpClient.
This explains the reason and the background.
Now I restored the selenium-webdriver-junit4/build.gradle
file to point the selenium-java-v4.14.1
seleniumVersion = "4.14.1"
//seleniumVersion = "4.13.0"
And I executed the io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test
again. I got the error again.
> Task :selenium-webdriver-junit4:testClasses
2023-10-21 21:11:48 [Test worker] DEBUG i.g.bonigarcia.wdm.WebDriverManager.<init>(225) - Using WebDriverManager 5.5.3
2023-10-21 21:11:48 [Test worker] DEBUG i.g.b.wdm.cache.ResolutionCache.checkKeyInResolutionCache(186) - Resolution chrome=118 in cache (valid until 22:08:31 21/10/2023 JST)
2023-10-21 21:11:48 [Test worker] DEBUG i.g.b.wdm.cache.ResolutionCache.checkKeyInResolutionCache(186) - Resolution chrome118=118.0.5993.70 in cache (valid until 21:08:31 22/10/2023 JST)
2023-10-21 21:11:48 [Test worker] INFO i.g.bonigarcia.wdm.WebDriverManager.resolveDriverVersion(1217) - Using chromedriver 118.0.5993.70 (resolved driver for Chrome 118)
2023-10-21 21:11:48 [Test worker] DEBUG i.g.bonigarcia.wdm.WebDriverManager.manage(1172) - Driver chromedriver 118.0.5993.70 found in cache
2023-10-21 21:11:48 [Test worker] INFO i.g.bonigarcia.wdm.WebDriverManager.exportDriver(1270) - Exporting webdriver.chrome.driver as /Users/kazuakiurayama/.cache/selenium/chromedriver/mac64/118.0.5993.70/chromedriver
java.lang.NoClassDefFoundError: org/openqa/selenium/remote/http/netty/NettyClient$Factory
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:467)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.nextProviderClass(ServiceLoader.java:1217)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1228)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1273)
at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1309)
at java.base/java.util.ServiceLoader$3.hasNext(ServiceLoader.java:1393)
at java.base/java.util.Spliterators$IteratorSpliterator.trySplit(Spliterators.java:1820)
at java.base/java.util.stream.AbstractTask.compute(AbstractTask.java:308)
at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:754)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:686)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateParallel(ReduceOps.java:927)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at org.openqa.selenium.remote.http.HttpClient$Factory.create(HttpClient.java:55)
at org.openqa.selenium.remote.http.HttpClient$Factory.createDefault(HttpClient.java:74)
at org.openqa.selenium.remote.HttpCommandExecutor$DefaultClientFactoryHolder.<clinit>(HttpCommandExecutor.java:57)
at org.openqa.selenium.remote.HttpCommandExecutor.getDefaultClientFactory(HttpCommandExecutor.java:61)
at org.openqa.selenium.remote.HttpCommandExecutor.<init>(HttpCommandExecutor.java:95)
at org.openqa.selenium.remote.service.DriverCommandExecutor.<init>(DriverCommandExecutor.java:89)
at org.openqa.selenium.chromium.ChromiumDriverCommandExecutor.<init>(ChromiumDriverCommandExecutor.java:43)
at org.openqa.selenium.chrome.ChromeDriver$ChromeDriverCommandExecutor.<init>(ChromeDriver.java:115)
at org.openqa.selenium.chrome.ChromeDriver.generateExecutor(ChromeDriver.java:105)
at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:88)
at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:83)
at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:51)
at io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test.setup(HelloWorldChromeJUnit4Test.java:46)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:112)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:40)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:60)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:52)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at jdk.proxy1/jdk.proxy1.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: java.lang.ClassNotFoundException: org.openqa.selenium.remote.http.netty.NettyClient$Factory
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
... 83 more
Now I should read the stacktrace carefully.
I noticed this line:
at org.openqa.selenium.remote.http.HttpClient$Factory.create(HttpClient.java:55)
at org.openqa.selenium.remote.http.HttpClient$Factory.createDefault(HttpClient.java:74)
I suppose that the org.openqa.selenium.remote.http.HttpClient$Factory.create()
in selenium-java-4.14.1 should instanciate the org.openqa.selenium.remote.http.jdk.JdkHttpClient
class. However, actually it tries to instanciate the
org.openqa.selenium.reqmote.http.netty.NettyClient
class; and failed because the class binary is not contained in the jar of v4.14.1. That is the scenario how the original error.
Now I have got more focused. In selenium-java4.14-1, why the HttpClients$Factory.create()
tries to instanciate NettyClient
instead of JdkHttpClient
?
I should look at the source of org.openqa.selenium.remote.http.HttpClient$Factory.create()
.
...
In the aforementioned zip file, I found a jar selenium-http-4.14.1-sources.jar
. In the jar, org.openqa.selenium.remote.http.HttpClient
class was contained:
You can read the source at
I think I could trace how the HttpClients
class instanciates the org.openqa.selenium.remote.http.jdk.JdkHttpClient
.
I have studied the source of selenium-java-4.14.1 more.
the org.openqa.selenium.remote.http.HttpClient$Factory.createDefault()
method seems trying to instanciate the org.openqa.selenium.remote.http.jdk.JdkHttpClient
class.
static Factory createDefault() {
return create(System.getProperty("webdriver.http.factory", "jdk-http-client"));
}
However, in the StackTrace message of io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test
, the HttpClient$Factory.createDefault() actually tried to isntanciate the org.openqa.selenium.reqmote.http.netty.NettyClient
class, and failed due to ClassNotFound
exception.
Why this happens?
I have a doubt about https://github.com/SeleniumHQ/selenium/blob/selenium-4.14.1-java/java/src/org/openqa/selenium/remote/http/HttpClient.java
static Factory createDefault() {
return create(System.getProperty("webdriver.http.factory", "jdk-http-client"));
}
According to https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#getProperty-java.lang.String-java.lang.String-
public static String getProperty(String key, String def)
Gets the system property indicated by the specified key.
First, if there is a security manager, its checkPropertyAccess method is called with the key as its argument.
If there is no current set of system properties, a set of system properties is first created and initialized in the same manner as for the getProperties method.
When I exected the io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test
class, If the system property "webdriver.http.factory" has value "netty", then it is possible to result in a Exception java.lang.ClassNotFoundException: org.openqa.selenium.remote.http.netty.NettyClient$Factory
.
static Factory createDefault() {
return create(System.getProperty("webdriver.http.factory", "netty"));
}
I tried a study in io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test
. I changed the code a bit
@BeforeClass
public static void setupClass() {
System.out.println("*** webdriver.http.factory 1 = " + System.getProperty("webdriver.http.factory"));
WebDriverManager.chromedriver().setup();
System.out.println("*** webdriver.http.factory 2 = " + System.getProperty("webdriver.http.factory"));
}
When I ran the test, I got the following output in the console:
> Task :selenium-webdriver-junit4:testClasses
*** webdriver.http.factory 1 = null
2023-10-21 22:37:30 [Test worker] DEBUG i.g.bonigarcia.wdm.WebDriverManager.<init>(225) - Using WebDriverManager 5.5.3
2023-10-21 22:37:31 [Test worker] DEBUG i.g.b.wdm.cache.ResolutionCache.checkKeyInResolutionCache(186) - Resolution chrome=118 in cache (valid until 23:34:54 21/10/2023 JST)
2023-10-21 22:37:31 [Test worker] DEBUG i.g.b.wdm.cache.ResolutionCache.checkKeyInResolutionCache(186) - Resolution chrome118=118.0.5993.70 in cache (valid until 21:08:31 22/10/2023 JST)
2023-10-21 22:37:31 [Test worker] INFO i.g.bonigarcia.wdm.WebDriverManager.resolveDriverVersion(1217) - Using chromedriver 118.0.5993.70 (resolved driver for Chrome 118)
2023-10-21 22:37:31 [Test worker] DEBUG i.g.bonigarcia.wdm.WebDriverManager.manage(1172) - Driver chromedriver 118.0.5993.70 found in cache
2023-10-21 22:37:31 [Test worker] INFO i.g.bonigarcia.wdm.WebDriverManager.exportDriver(1270) - Exporting webdriver.chrome.driver as /Users/kazuakiurayama/.cache/selenium/chromedriver/mac64/118.0.5993.70/chromedriver
*** webdriver.http.factory 2 = null
This proved that the system property webdriver.http.factory
is numm at runtime.
Another study in the same in io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test. I set the system property webdriver.http.factory
with value jdk-http-client
.
@BeforeClass
public static void setupClass() {
WebDriverManager.chromedriver().setup();
System.setProperty("webdriver.http.factory", "jdk-http-client");
System.out.println("webdriver.http.factory: " + System.getProperty("webdriver.http.factory"));
}
The output was:
> Task :selenium-webdriver-junit4:testClasses
2023-10-21 22:43:01 [Test worker] DEBUG i.g.bonigarcia.wdm.WebDriverManager.<init>(225) - Using WebDriverManager 5.5.3
2023-10-21 22:43:02 [Test worker] DEBUG i.g.b.wdm.cache.ResolutionCache.checkKeyInResolutionCache(186) - Resolution chrome=118 in cache (valid until 23:34:54 21/10/2023 JST)
2023-10-21 22:43:02 [Test worker] DEBUG i.g.b.wdm.cache.ResolutionCache.checkKeyInResolutionCache(186) - Resolution chrome118=118.0.5993.70 in cache (valid until 21:08:31 22/10/2023 JST)
2023-10-21 22:43:02 [Test worker] INFO i.g.bonigarcia.wdm.WebDriverManager.resolveDriverVersion(1217) - Using chromedriver 118.0.5993.70 (resolved driver for Chrome 118)
2023-10-21 22:43:02 [Test worker] DEBUG i.g.bonigarcia.wdm.WebDriverManager.manage(1172) - Driver chromedriver 118.0.5993.70 found in cache
2023-10-21 22:43:02 [Test worker] INFO i.g.bonigarcia.wdm.WebDriverManager.exportDriver(1270) - Exporting webdriver.chrome.driver as /Users/kazuakiurayama/.cache/selenium/chromedriver/mac64/118.0.5993.70/chromedriver
webdriver.http.factory: jdk-http-client
java.lang.NoClassDefFoundError: org/openqa/selenium/remote/http/netty/NettyClient$Factory
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:467)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.nextProviderClass(ServiceLoader.java:1217)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1228)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1273)
at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1309)
at java.base/java.util.ServiceLoader$3.hasNext(ServiceLoader.java:1393)
at java.base/java.util.Spliterators$IteratorSpliterator.trySplit(Spliterators.java:1820)
at java.base/java.util.stream.AbstractTask.compute(AbstractTask.java:308)
at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:754)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:686)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateParallel(ReduceOps.java:927)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at org.openqa.selenium.remote.http.HttpClient$Factory.create(HttpClient.java:55)
at org.openqa.selenium.remote.http.HttpClient$Factory.createDefault(HttpClient.java:74)
at org.openqa.selenium.remote.HttpCommandExecutor$DefaultClientFactoryHolder.<clinit>(HttpCommandExecutor.java:57)
at org.openqa.selenium.remote.HttpCommandExecutor.getDefaultClientFactory(HttpCommandExecutor.java:61)
at org.openqa.selenium.remote.HttpCommandExecutor.<init>(HttpCommandExecutor.java:95)
at org.openqa.selenium.remote.service.DriverCommandExecutor.<init>(DriverCommandExecutor.java:89)
at org.openqa.selenium.chromium.ChromiumDriverCommandExecutor.<init>(ChromiumDriverCommandExecutor.java:43)
at org.openqa.selenium.chrome.ChromeDriver$ChromeDriverCommandExecutor.<init>(ChromeDriver.java:115)
at org.openqa.selenium.chrome.ChromeDriver.generateExecutor(ChromeDriver.java:105)
at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:88)
at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:83)
at org.openqa.selenium.chrome.ChromeDriver.<init>(ChromeDriver.java:51)
at io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test.setup(HelloWorldChromeJUnit4Test.java:47)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:112)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:40)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:60)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:52)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
at jdk.proxy1/jdk.proxy1.$Proxy2.processTestClass(Unknown Source)
at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:113)
at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:65)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)
Caused by: java.lang.ClassNotFoundException: org.openqa.selenium.remote.http.netty.NettyClient$Factory
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
... 83 more
I set the value jdk-http-client
to the system property webdriver.http.factory
.
So I expected that the error java.lang.ClassNotFoundException: org.openqa.selenium.remote.http.netty.NettyClient$Factory
won't occur any longer.
But in fact as the output above shows, the error repeated. Why?
Now I have got a doubt: in the classpath for the test, there are 2 binary files with the same name org.openqa.selenium.remote.http.HttpClient
. One is generated as v4.14.1, another is generated as v4.13.0.
I want the HttpClient
class of v4.14.1 to be used but in fact the HttpClient
class of v4.13.0 is used, and caused an error.
So, I need to lookup the class in the whole classpath.
I wanted to confirm that the HttpClient
class is loaded out of the proper version of jar file.
In io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test, I tried
@BeforeClass
public static void setupClass() throws URISyntaxException {
WebDriverManager.chromedriver().setup();
String path = byGetProtectionDomain(org.openqa.selenium.remote.http.HttpClient.class);
System.out.println("HttpClient class was loaded out of " + path);
}
static String byGetProtectionDomain(Class clazz) throws URISyntaxException {
URL url = clazz.getProtectionDomain().getCodeSource().getLocation();
return Paths.get(url.toURI()).toString();
}
This emitted the following output
2023-10-21 23:28:36 [Test worker] INFO i.g.bonigarcia.wdm.WebDriverManager.exportDriver(1270) - Exporting webdriver.chrome.driver as /Users/kazuakiurayama/.cache/selenium/chromedriver/mac64/118.0.5993.70/chromedriver
HttpClient class was loaded out of /Users/kazuakiurayama/.gradle/caches/modules-2/files-2.1/org.seleniumhq.selenium/selenium-http/4.14.1/8e37700f9fc1e727aabd39b7335b277d310cb55a/selenium-http-4.14.1.jar
This is normal. Just as I expected. Nothing curious. Fine.
Further study on the io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test
.
@BeforeClass
public static void setupClass() {
WebDriverManager.chromedriver().setup();
Object result = org.openqa.selenium.remote.http.HttpClient.Factory.create("jdk-http-client");
System.out.println("Factory : " + result.getClass().getName());
}
This output:
2023-10-21 23:44:50 [Test worker] ERROR io.qameta.allure.AllureLifecycle.updateTestCase(394) - Could not update test case: test case with uuid 6b067f77-5771-4757-b316-d1b2a0e36fb5 not found
java.lang.NoClassDefFoundError: org/openqa/selenium/remote/http/netty/NettyClient$Factory
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:467)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.nextProviderClass(ServiceLoader.java:1217)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1228)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1273)
at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1309)
at java.base/java.util.ServiceLoader$3.hasNext(ServiceLoader.java:1393)
at java.base/java.util.Spliterators$IteratorSpliterator.trySplit(Spliterators.java:1820)
at java.base/java.util.stream.AbstractTask.compute(AbstractTask.java:308)
at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:754)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:686)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateParallel(ReduceOps.java:927)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at org.openqa.selenium.remote.http.HttpClient$Factory.create(HttpClient.java:55)
at io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test.setupClass(HelloWorldChromeJUnit4Test.java:43)
...
A big surprise to me! The output message tells me that this statement
Object result = org.openqa.selenium.remote.http.HttpClient.Factory.create("jdk-http-client");
raised java.lang.NoClassDefFoundError: org/openqa/selenium/remote/http/netty/NettyClient$Factory
It seems that I encountered a problem of the org.openqa.selenium.remote.http.HttpClient
class. Especially the create(String)
method seems to be mal-functioning.
An inspiring post
Unknown HttpClient factory netty when create remote webdriver
Run mvn depndency:tree and watch the output, you must be having multiple different versions of selenium artifacts in the classpath. I suppose webdrivermanager brings an unwanted selenium version as a transitive dependency.
I will create another git branch kazuraham10hacked
where I will investigate this issue (java.lang.NoClassDefFoundError: org/openqa/selenium/remote/http/netty/NettyClient$Factory
) in the org.seleniumhq.selenium:selenium-java:4.14.1
in more detail.
In the branch kazurayam10hacked
, I will add a new subproject selenium-webdriver-junit4_hacked
.
In the selenium-webdriver-junit4_hacked
subproject, I will try nasty code changes to find more.
I created a new branch kazurayam10hacked.
https://github.com/kazurayam/selenium-webdriver-java/commit/602b36f1e4dc5ee19fe8519dda18c167fe8b451f
In that branch, I executed a test io.github.nobigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test
I silently passed. I did not see java.lang.NoClassDefFoundError
.
This experiment tells me that I would be able to find the reason of "NoClassDefFoundError for NettyClient" in some differences between the selenim-webdriver-junit4
subproject and the selenium-webdriver-junit4_hacked
subproject.
I should investicate the classpath of the selenium-webdriver-junit4
subproject in more detail.
I guess that there are 2 or more entries of org.openqa.selenium.remote.http.HttpClient
binary in the jars in the testImplementation
dependency. The org.seleniumhq.selenium:selenium-java:4.14.1
will contain a HttpClient
of the version 4.14.x, of course. But, I suppose, not only that, there will be more of the version 4.13.x or older. I guess the older HttpClient
is loaded and refered to when I execute the junit4 test; so the java.lang.NoClassDefFoundError
for NettyClient occurs.
So, in the selenium-webdriver-junit4/build.gradle
file, I would develop a custom Gradle task listJarsContainingClazz
that reports what I want to see.
The org.openqa.selenium.remote.http.HttpClient$Factory.create method uses java.util.ServiceLoader
class.
What is ServiceLoader? I would read the following tutorial to learn some about the java.util.ServiceLoader
.
I have got a break through.
I found that the dependency to the com.codebone:selenide:xx.xx.xx
is significant for the NoClassDefFoundError for NettyClient
. I can prove it.
I have created a git branch kazurayam10hacked
. In there I have
testImplementation("com.codeborne:selenide:${selenideVersion}") {
exclude group: "org.seleniumhq.selenium", module: "selenium-java"
exclude group: "io.github.bonigarcia", module: "webdrivermanager"
exclude group: "org.apache.httpcomponents.client5", module: "httpclient5"
}
I ran the test, I got the NoClassDefinitionFoundError for NettyClient
.
java.lang.NoClassDefFoundError: org/openqa/selenium/remote/http/netty/NettyClient$Factory
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1017)
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862)
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681)
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:467)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.nextProviderClass(ServiceLoader.java:1217)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNextService(ServiceLoader.java:1228)
at java.base/java.util.ServiceLoader$LazyClassPathLookupIterator.hasNext(ServiceLoader.java:1273)
at java.base/java.util.ServiceLoader$2.hasNext(ServiceLoader.java:1309)
at java.base/java.util.ServiceLoader$3.hasNext(ServiceLoader.java:1393)
at java.base/java.util.Spliterators$IteratorSpliterator.trySplit(Spliterators.java:1820)
at java.base/java.util.stream.AbstractTask.compute(AbstractTask.java:308)
at java.base/java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:754)
at java.base/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
at java.base/java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:686)
at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateParallel(ReduceOps.java:927)
at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233)
at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
at org.openqa.selenium.remote.http.HttpClient$Factory.create(HttpClient.java:55)
at io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test.setupClass(HelloWorldChromeJUnit4Test.java:40)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
at org.junit.internal.runners.statements.RunBefores.invokeMethod(RunBefores.java:33)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:24)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:112)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:40)
at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:60)
at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:52)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
...
On the other hand, I have created another git branch kazurayam10hacked_workedaround
. In there I have
build.gradle where I commented out (removed) the dependency to the selenide
library
testImplementation("org.seleniumhq.selenium:selenium-java:${seleniumVersion}")
testImplementation("junit:junit:${junit4Version}")
testImplementation("org.assertj:assertj-core:${assertjVersion}")
testImplementation("io.github.bonigarcia:webdrivermanager:${wdmVersion}")
/*
testImplementation("com.codeborne:selenide:${selenideVersion}") {
exclude group: "org.seleniumhq.selenium", module: "selenium-java"
exclude group: "io.github.bonigarcia", module: "webdrivermanager"
exclude group: "org.apache.httpcomponents.client5", module: "httpclient5"
}
*/
- the [test class](https://github.com/kazurayam/selenium-webdriver-java/blob/kazurayam10hacked_workedaround/selenium-webdriver-junit4_hacked/src/test/java/io/github/bonigarcia/webdriver/junit4/ch02/helloworld/HelloWorldChromeJUnit4Test.java) is just the same as the branch `kazurayam10hacked`
When I ran the test in the `kazurayam10hacked_workedaround`, the test passed silently. The `NoClassDefFoundError` did not come up.
Task :selenium-webdriver-junit4_hacked:compileJava NO-SOURCE Task :selenium-webdriver-junit4_hacked:processResources NO-SOURCE Task :selenium-webdriver-junit4_hacked:classes UP-TO-DATE Task :selenium-webdriver-junit4_hacked:compileTestJava Task :selenium-webdriver-junit4_hacked:processTestResources NO-SOURCE Task :selenium-webdriver-junit4_hacked:testClasses 10:45:44.571 [Test worker] DEBUG io.github.bonigarcia.wdm.WebDriverManager -- Using WebDriverManager 5.5.3 10:45:45.213 [Test worker] DEBUG io.github.bonigarcia.wdm.cache.ResolutionCache -- Resolution chrome=118 in cache (valid until 11:36:36 23/10/2023 JST) 10:45:45.220 [Test worker] DEBUG io.github.bonigarcia.wdm.cache.ResolutionCache -- Resolution chrome118=118.0.5993.70 in cache (valid until 08:24:15 24/10/2023 JST) 10:45:45.224 [Test worker] INFO io.github.bonigarcia.wdm.WebDriverManager -- Using chromedriver 118.0.5993.70 (resolved driver for Chrome 118) 10:45:45.252 [Test worker] DEBUG io.github.bonigarcia.wdm.WebDriverManager -- Driver chromedriver 118.0.5993.70 found in cache 10:45:45.254 [Test worker] INFO io.github.bonigarcia.wdm.WebDriverManager -- Exporting webdriver.chrome.driver as /Users/kazuakiurayama/.cache/selenium/chromedriver/mac64/118.0.5993.70/chromedriver Factory : org.openqa.selenium.remote.http.jdk.JdkHttpClient$Factory Task :selenium-webdriver-junit4_hacked:test io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test > test PASSED Deprecated Gradle features were used in this build, making it incompatible with Gradle 9.0. You can use '--warning-mode all' to show the individual deprecation warnings and determine if they come from your own scripts or plugins. For more on this, please refer to https://docs.gradle.org/8.4/userguide/command_line_interface.html#sec:command_line_warnings in the Gradle documentation. BUILD SUCCESSFUL in 10s 2 actionable tasks: 2 executed 10:45:52: Execution finished ':selenium-webdriver-junit4_hacked:test --tests "io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test.test"'.
So, why the "NoClassDefFoundError for NettyClient" occurs when I have a dependency to the selenide library? The is the question I should dig into.
Let me check the source of the selenide project:
I noticed that in the source code of selenide v6.19.1, they have META-INF/services/org.openqa.selenium.remote.http.HttpClient$Factory
file, as follows
Its content is a single line
com.codeborne.selenide.webdriver.SelenideNettyClientFactory
The source code of the SelenideNettyClientFactory is
In there I found a problem:
import org.openqa.selenium.remote.http.netty.NettyClient;
...
public class SelenideNettyClientFactory extends NettyClient.Factory {
...
The org.openqa.selenium.remote.http.netty.NettyClient
is available in the selenium-java v4.13 and older. But it is NOT available since selenium v4.14.x.
I believe that the selenide v6.19.1 does not work with the selenium-java v4.14.x.
This could be the reason why I got "NoClassDefFoundError for NettyClient$Factory" in the kazurayam10hacked branch.
Let me try explaining why the java.lang.NoClassDefFoundError: org/openqa/selenium/remote/http/netty/NettyClient$Factory
exception is raised only when the jar of selenide v6.19.1 is inserted into the testImplementation dependency in the build.gradle file at https://github.com/kazurayam/selenium-webdriver-java/blob/kazurayam10hacked/selenium-webdriver-junit4/build.gradle
I would start reading read the code of org.openqa.selenium.remote.http.HttpClient$Factory.create. It does the following:
public interface HttpClient extends Closeable, HttpHandler {
interface Factory {
static Factory create(String name) {
ServiceLoader<HttpClient.Factory> loader =
ServiceLoader.load(HttpClient.Factory.class, HttpClient.Factory.class.getClassLoader());
What does the ServiceLoader.load(HttpClient.Factory.class, ...
does?
ServiceLoader.load()
scans the runtime classpath to look up all class files that implements the org.openqa.selenium.remote.http.HttpClient$Factory
interface
With the selenide-6.19.1.jar and the selenium-java-4.14.1.jar are injected , ServiceLoader.load()
will find 2 class files that implements the HttpClient$Factory
interface.
org.openqa.selenium.remote.http.jdk.JdkHttpClient$Factory
com.codeborne.selenide.webdriver.SelenideNettyClientFactory
ServiceLoader.load()
will try to instantiate these 2 clasess.
As soon as ServiceLoad.load()
tries to instantiate the com.codeborne.selenide.webdriver.SelenideNettyClientFactory
, the java.lang.NoClassDefFoundError: org/openqa/selenium/remote/http/netty/NettyClient$Factory
exception will be raised because the selenium-java-4.19.1.jar does not contain the class file of org.openqa.selenium.remote.http.netty.NettyClient
(THE END)
According to https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-java, the 4.19.x of selenium-java was releast at 10, Oct 2023. Just recently! Therefore, it is likely that the selenide project has not come up with this new release.
How the Selenide project is working to do with the selenium-java v4.19?
at 23, Oct 2023, I checked the issue list of the selenide project
I found no issue that tells Selenide to work with Selenium-java v14.4.x. It seems that they (Selenide project) is not yet aware of this issue yet. So I have created a new issue in the selenide list to inform the version confict, in the hope that they address it in the near future.
If I use the v4.13.x of selenium-java library instead of v4.14.x, then the "NoClassDefFoundError" will disappear.
I would like to propose to @binogarcia to tentatively downgrade selenium-java library from v4.14.1 to v4.13.0.
This tentative change will enable all codes to compile and run.
I will look at the selenide project's progress. When they release a new version that is compatible with selenium-java-4.14.x, then I would be able to notify @binogarcia that he can re-bump the selenium-java library to the v4.14.1 again.
I have changed 4 gradle.build files and 4 pom.xml files in the kazurayam10
branch. See the tail:
https://github.com/kazurayam/selenium-webdriver-java/commit/b80428266158b1bba5168b26c6643a273ccce849
With this change, all of sample test codes in the selenium-webdriver-java book now compiles both by Gradle and Maven. Chers!
:~/github/selenium-webdriver-java (kazurayam10)
$ gradle -q clean compileTestJava
... (no errors)
:~/github/selenium-webdriver-java (kazurayam10)
$ mvn clean test-compile
[INFO] Scanning for projects...
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Build Order:
[INFO]
[INFO] selenium-webdriver-junit4 [jar]
[INFO] selenium-webdriver-junit5 [jar]
[INFO] selenium-webdriver-junit5-seljup [jar]
[INFO] selenium-webdriver-testng [jar]
[INFO] selenium-webdriver-java [pom]
[INFO]
[INFO] -----------< io.github.bonigarcia:selenium-webdriver-junit4 >-----------
[INFO] Building selenium-webdriver-junit4 1.2.0 [1/5]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ selenium-webdriver-junit4 ---
[INFO] Deleting /Users/kazuakiurayama/github/selenium-webdriver-java/selenium-webdriver-junit4/target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ selenium-webdriver-junit4 ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 3 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ selenium-webdriver-junit4 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/kazuakiurayama/github/selenium-webdriver-java/selenium-webdriver-junit4/target/classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ selenium-webdriver-junit4 ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 13 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ selenium-webdriver-junit4 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 217 source files to /Users/kazuakiurayama/github/selenium-webdriver-java/selenium-webdriver-junit4/target/test-classes
[INFO]
[INFO] -----------< io.github.bonigarcia:selenium-webdriver-junit5 >-----------
[INFO] Building selenium-webdriver-junit5 1.2.0 [2/5]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ selenium-webdriver-junit5 ---
[INFO] Deleting /Users/kazuakiurayama/github/selenium-webdriver-java/selenium-webdriver-junit5/target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ selenium-webdriver-junit5 ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 3 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ selenium-webdriver-junit5 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/kazuakiurayama/github/selenium-webdriver-java/selenium-webdriver-junit5/target/classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ selenium-webdriver-junit5 ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 13 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ selenium-webdriver-junit5 ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 212 source files to /Users/kazuakiurayama/github/selenium-webdriver-java/selenium-webdriver-junit5/target/test-classes
[INFO]
[INFO] -------< io.github.bonigarcia:selenium-webdriver-junit5-seljup >--------
[INFO] Building selenium-webdriver-junit5-seljup 1.2.0 [3/5]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ selenium-webdriver-junit5-seljup ---
[INFO] Deleting /Users/kazuakiurayama/github/selenium-webdriver-java/selenium-webdriver-junit5-seljup/target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ selenium-webdriver-junit5-seljup ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 3 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ selenium-webdriver-junit5-seljup ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/kazuakiurayama/github/selenium-webdriver-java/selenium-webdriver-junit5-seljup/target/classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ selenium-webdriver-junit5-seljup ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 14 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ selenium-webdriver-junit5-seljup ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 203 source files to /Users/kazuakiurayama/github/selenium-webdriver-java/selenium-webdriver-junit5-seljup/target/test-classes
[INFO]
[INFO] -----------< io.github.bonigarcia:selenium-webdriver-testng >-----------
[INFO] Building selenium-webdriver-testng 1.2.0 [4/5]
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ selenium-webdriver-testng ---
[INFO] Deleting /Users/kazuakiurayama/github/selenium-webdriver-java/selenium-webdriver-testng/target
[INFO]
[INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ selenium-webdriver-testng ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 3 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ selenium-webdriver-testng ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to /Users/kazuakiurayama/github/selenium-webdriver-java/selenium-webdriver-testng/target/classes
[INFO]
[INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ selenium-webdriver-testng ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 15 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.1:testCompile (default-testCompile) @ selenium-webdriver-testng ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 212 source files to /Users/kazuakiurayama/github/selenium-webdriver-java/selenium-webdriver-testng/target/test-classes
[INFO]
[INFO] ------------< io.github.bonigarcia:selenium-webdriver-java >------------
[INFO] Building selenium-webdriver-java 1.0.0-SNAPSHOT [5/5]
[INFO] --------------------------------[ pom ]---------------------------------
[INFO]
[INFO] --- maven-clean-plugin:2.5:clean (default-clean) @ selenium-webdriver-java ---
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] selenium-webdriver-junit4 1.2.0 .................... SUCCESS [ 9.671 s]
[INFO] selenium-webdriver-junit5 1.2.0 .................... SUCCESS [ 3.052 s]
[INFO] selenium-webdriver-junit5-seljup 1.2.0 ............. SUCCESS [ 2.581 s]
[INFO] selenium-webdriver-testng 1.2.0 .................... SUCCESS [ 1.911 s]
[INFO] selenium-webdriver-java 1.0.0-SNAPSHOT ............. SUCCESS [ 0.024 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 17.387 s
[INFO] Finished at: 2023-10-23T21:11:36+09:00
[INFO] ------------------------------------------------------------------------
In response to the https://github.com/selenide/selenide/issues/2525, a selenide expert wrote about the selenide and the selenium-java issue:
This release shouldn't work with selenium 4.14.1 required java 11, because selenide 6.19.1 target java 8. Please wait until selenide 7.0.0 release, it will target java 17 and will bundled and work with latest selenium release.
I noticed that the selenide project already has a branch named "upgrade-to-java17".
However, I guess that @binogarcia have to wait for long months for the selenide project to work with JDK17 and selenium-java 4.14.x.
This project employs dependabot.
https://github.com/kazurayam/selenium-webdriver-java/blob/master/.github/dependabot.yml
I want the dependabot to ignore org.seleniumhq.selenium:selenium-java
so that I can stay with the selenium-java-v4.10.0
I found a closely related issue
which includes a post
titusfortner commented on Mar 9 AsyncHttp Client has not been actively maintained (looks like this just changed), so we've been requesting people upgrade to the Java 11 HTTP client https://www.selenium.dev/blog/2022/using-java11-httpclient/ Looks like latest version of AsyncHttp still relies on Netty 4 and is compiled with Java 11 anyway? So I don't think continuing with that library is going to be the solution regardless.
Artur- commented [on Mar 9] (https://github.com/SeleniumHQ/selenium/issues/11750#issuecomment-1460580132) Adding
<dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-http-jdk-client</artifactId> </dependency>
and
System.setProperty("webdriver.http.factory", "jdk-http-client");
makes tests work again
Possibly I need to do the same in the selenium-webdriver-java project: add dependency to the selenium-http-jdk-client jar, and set system property "webdriver.http.factory" to be "jdk-http-client".
See https://selenide.org/2023/10/25/selenide-7.0.0/#java17
The selenide project just released the v7.0.0 which targets Java 17.
This means that the selenium-webdriver-java project should be able to go for the selenium-java v4.14.x
After I fixed #9, I tried to run the
io.github.bonigarcia.webdriver.junit4.ch02.helloworld.HelloWorldChromeJUnit4Test
class. Then I got the following error: