appium / java-client

Java language binding for writing Appium Tests, conforms to W3C WebDriver Protocol
Apache License 2.0
1.18k stars 752 forks source link

Not able to run mobile app tests using mvn clean test command and seen errors java. lang. NoClassDefFoundError: org/openqa/selenium/remote/RemoteWebElement & java. lang. NoClassDefFoundError: io/appium/java_client/proxy/HasMethodCallListeners. #2118

Open pothurajtharun opened 4 months ago

pothurajtharun commented 4 months ago

Description

When i try to run the mobile app test cases using the below configurations then I'm facing multiple issues as mentioned in this ticket.

Environment

Details

I ran mobile app test cases on the above configurations using maven commands mvn clean test but saw multiple errors as mentioned in the above description and not able to run the tests successfully.

Code To Reproduce Issue [ Good To Have ]

Sorry at the moment I can't share the code as it is company licensed.

Exception Stacktraces

9.0.0 Error Stack Trace:

java. lang. NoClassDefFoundError: org/openqa/selenium/remote/RemoteWebElement 
at java.base/java. lang. ClassLoader. defineClass1 (Native Method) at java.base/java. lang. ClassLoader. defineClass (ClassLoader. java:1027)
at net. bytebuddy. dynamic. loading. ByteArrayClassLoader .access$300 (ByteArrayClassLoader. java:57) 
at net. bytebuddy. dynamic. loading. ByteArrayClassLoader$ClassDefinitionAction.run(ByteArrayClassLoader.java:687) 
at net. bytebuddy. dynamic. loading. ByteArrayClassLoader$ClassDefinitionAction.run(ByteArrayClassLoader.java:639) 
at java.base/java.security.AccessController. doPrivileged (AccessController. java:400) at net.bytebuddy.dynamic. loading. ByteArrayClassLoader .doPrivileged (ByteArrayClassLoader. java) 
at net.bytebuddy.dynamic.loading.ByteArrayClassLoader.findClass(ByteArrayClassLoader.java:406) 
at java.base/java.lang. ClassLoader. loadClass (ClassLoader. java: 593) 
at java.base/java. lang. ClassLoader. loadClass (ClassLoader. java:526) 
at java.base/java. lang. Class. forName (Native Method) at java.base/java. lang. Class. forName (Class. java: 534) 
at java.base/java. lang. Class.forName (Class. java: 513)
at net.bytebuddy.dynamic.loading. ByteArrayClassLoader. load (ByteArrayClassLoader. java:361) 
at net.bytebuddy .dynamic. loading. ClassLoadingStrategy$Default$WrappingDispatcher.load(ClassLoadingStrategy.java:367) 
at net.bytebuddy.dynamic. loading. ClassLoadingStrategy$Default. load (ClassLoadingStrategy. java:148) 
at net.bytebuddy .dynamic. TypeResolutionStrategy$Passive.initialize (TypeResolutionStrategy. java: 101) 
at net.bytebuddy.dynamic.DynamicType$Default$Unloaded. load (DynamicType. java:6317) 
at io.appium.java_client.proxy. Helpers. createProxy (Helpers.java:121)
at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:96)
at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:71)
at io.appium.java_client.pagefactory.AppiumFieldDecorator.proxyForAnElement(AppiumFieldDecorator.java:248)

9.1.0 Error Stack Trace:

java. lang. NoClassDefFoundError: io/appium/java_client/proxy/HasMethodCallListeners at java.base/java. lang. ClassLoader. defineClass1 (Native Method) 
at java.base/java.lang. ClassLoader .defineClass (ClassLoader. java: 1027)
at net.bytebuddy.dynamic.loading. ByteArrayClassLoader.access$300 (ByteArrayClassLoader.java:57) 
at net. bytebuddy. dynamic. loading. ByteArrayClassLoader$ClassDefinitionAction.run(ByteArrayClassLoader.java:687) 
at net.bytebuddy.dynamic. loading.ByteArrayClassLoader$ClassDefinitionAction.run(ByteArrayClassLoader.java:639) 
at java.base/java.security.AccessController .doPrivileged (AccessController. java: 400) 
at net.bytebuddy. dynamic. loading. ByteArrayClassLoader. doPrivileged (ByteArrayClassLoader. java) 
at net.bytebuddy.dynamic.loading. ByteArrayClassLoader. findClass (ByteArrayClassLoader. java: 406) 
at java.base/java. lang. ClassLoader. loadClass (ClassLoader. java: 593) 
at java.base/java. lang. ClassLoader. loadClass (ClassLoader. java:526) 
at java.base/java.lang.Class.forName0(Native Method) 
at java. base/java. lang. Class. forName (Class. java: 534) 
at java.base/java. lang. Class.forName (Class. java: 513)
at net.bytebuddy.dynamic.loading.ByteArrayClassLoader.load(ByteArrayClassLoader.java:361)
at net .bytebuddy. dynamic. loading. ClassLoadingStrategy$Default$WrappingDispatcher.load(ClassLoadingStrategy.java:367) 
at net.bytebuddy. dynamic. loading. ClassLoadingStrategy$Default. load(ClassLoadingStrategy. java: 148) 
at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:101) 
at net .bytebuddy. dynamic. DynamicType$Default$Unloaded. load (DynamicType.java: 6325) 
at io.appium.java_client.proxy. Helpers. createProxy (Helpers. java: 127)
at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:95)
at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:70)

Link To Appium Logs

9.0.0 Error Logs & Screenshots:

Error_9 0 0

appium-java-client-9.0.0.log

9.1.0 Error Logs & Screenshots:

Error_9 1 0

appium-java-client-9.1.0.log

Please take a look once and let me know if I'm missing something here. All the mentioned dependencies are available in pom.xml and class path.

Thanks in advance!

mykola-mokhnach commented 4 months ago

bytebuddy uses the system class loader to load classes. In order for classes to be visible to the system loader they must be enumerated in the classpath environment variable, -classpath, or -cp command line option.

pwebster-cpi commented 4 months ago

This appears to be similar to https://github.com/appium/java-client/issues/2058. I have faced the same issue ever since 8.5.1 was released. But starting with 9.1.0, the NoClassDefFoundError error has switched from RemoteWebElement to HasMethodCallListeners. I obey the compatibility matrix with Maven dependencies defined as suggested here.

@mykola-mokhnach, using your hint about enumerating specific classes in the -classpath command-line java option, I was able to eliminate the NoClassDefFoundError errors. I defined a shell environment variable defining paths to the missing JAR files:

export APPIUM_CLASSPATH=/Users/patrickwebster/.m2/repository/io/appium/java-client/9.1.0/java-client-9.1.0.jar:/Users/patrickwebster/.m2/repository/org/seleniumhq/selenium/selenium-api/4.17.0/selenium-api-4.17.0.jar:/Users/patrickwebster/.m2/repository/org/seleniumhq/selenium/selenium-remote-driver/4.17.0/selenium-remote-driver-4.17.0.jar:/Users/patrickwebster/.m2/repository/org/seleniumhq/selenium/selenium-support/4.17.0/selenium-support-4.17.0.jar

I extracted the IntelliJ IDEA Maven run command to the terminal, removed all IDEA-specific options and appended ":$APPIUM_CLASSPATH" to the value of my -classpath JVM option.

The result is no more NoClassDefFoundError errors, but this new error:

java.lang.ClassCastException: class org.openqa.selenium.remote.RemoteWebElement$ByteBuddy$byQ18vpl
    at java.base/java.lang.Class.asSubclass(Class.java:3640)
    at io.appium.java_client.proxy.Helpers.createProxy(Helpers.java:129)
    at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:95)
    at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:70)
    at io.appium.java_client.pagefactory.AppiumFieldDecorator.proxyForAnElement(AppiumFieldDecorator.java:258)
    at io.appium.java_client.pagefactory.AppiumFieldDecorator$1.proxyForLocator(AppiumFieldDecorator.java:157)
    at org.openqa.selenium.support.pagefactory.DefaultFieldDecorator.decorate(DefaultFieldDecorator.java:61)
    at io.appium.java_client.pagefactory.AppiumFieldDecorator.decorate(AppiumFieldDecorator.java:196)
    at org.openqa.selenium.support.PageFactory.proxyFields(PageFactory.java:109)
    at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:101)

These problems started when Byte Buddy was introduced in 8.5.1. I'm not sure how to configure the above hack into my project code. I am curious to know if anyone knows a setting in the POM.xml file that can append values to the JVM -classpath option. I experimented with various options like setting useSystemClassLoader to true or false, adding additionalClasspathElements, etc., but none of these achieved the results from the terminal command-line hack. I tried the latest Byte Buddy 1.14.12, but that did not help.

Environment

mykola-mokhnach commented 4 months ago

java.lang.ClassCastException: class org.openqa.selenium.remote.RemoteWebElement$ByteBuddy$byQ18vpl

This means the org.openqa.selenium.remote.RemoteWebElement class that was found in the classpath (and instrumented) is different from the one that is currently used. Probably because of Selenium lib versions conflict. Check your dependency tree to verify a single selenium lib version is in use.

pwebster-cpi commented 4 months ago

I removed my entire local Maven cache and the only version on disk after reloading dependencies is 4.17.0 when using java-client 9.1.0, or Selenium version 4.13.0 for java-client 8.5.1. If I make a single character change to the project POM.xml file by changing "8.5.1" to "8.5.0", everything works fine. The dependency list shows only one version of Selenium for any configuration. The effective POM.xml file also shows only one version of the Selenium library.

org.seleniumhq.selenium:selenium-api:4.13.0
org.seleniumhq.selenium:selenium-http:4.13.0
org.seleniumhq.selenium:selenium-json:4.13.0
org.seleniumhq.selenium:selenium-manager:4.13.0
org.seleniumhq.selenium:selenium-os:4.13.0
org.seleniumhq.selenium:selenium-remote-driver:4.13.0
org.seleniumhq.selenium:selenium-support:4.13.0
msr5464 commented 4 months ago

I am also getting exactly same issue when executing via mvn command:

If running on old versions like Selenium version 4.13.0 for java-client 8.5.1 then: java.lang.NoClassDefFoundError: org/openqa/selenium/remote/RemoteWebElement And If running on latest versions like Selenium version 4.17.0 for java-client 9.1.0 then: java.lang.NoClassDefFoundError: io/appium/java_client/proxy/HasMethodCallListeners

Please help with this!

Idoserovitz commented 4 months ago

bytebuddy uses the system class loader to load classes. In order for classes to be visible to the system loader they must be enumerated in the classpath environment variable, -classpath, or -cp command line option.

@mykola-mokhnach I am facing the same issue after updating to java-client version: 9.1.0. getting java.lang.NoClassDefFoundError: io/appium/java_client/proxy/HasMethodCallListeners

My question: how and why should I add this to the classpath? it is not an external jar file, it is already included in the project.. Thanks ahead!

pwebster-cpi commented 4 months ago

@mykola-mokhnach, is there any way we can get an option to use the old cglib code and bypass the new bytebuddy implementation? I'd like to move off of 8.5.0 to newer builds.

Thanks

mykola-mokhnach commented 4 months ago

@mykola-mokhnach, is there any way we can get an option to use the old cglib code and bypass the new bytebuddy implementation? I'd like to move off of 8.5.0 to newer builds.

Thanks

cglib integration has been dropped for a reason: the lib was poorly maintained and had a critical compatibility issue with newer java versions which had never been fixed.

I see several possible options there for you:

vinothpandian18 commented 2 months ago

I am also facing this same issue upon running my tests through mvn command on Selenium version 4.17.0 and Appium java client 9.1.0 with Appium server 2.x.x - java.lang.NoClassDefFoundError: io/appium/java_client/proxy/HasMethodCallListeners

I tried with different versions of Selenium and Appium Java client, but issues still happens.

And this is happening only when i am trying to run my tests via Jenkins. However I am able to run my mobile tests successfully in my local.

Please help with this! Appreciate if someone figure out any solution or workaround? Thanks!

AndrasFekete80 commented 2 months ago

Hi All, I also encountered the problem.

Caused by: java.lang.NoClassDefFoundError: io/appium/java_client/proxy/HasMethodCallListeners at java.base/java.lang.ClassLoader.defineClass1(Native Method) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1012) at net.bytebuddy.dynamic.loading.ByteArrayClassLoader.access$300(ByteArrayClassLoader.java:57) at net.bytebuddy.dynamic.loading.ByteArrayClassLoader$ClassDefinitionAction.run(ByteArrayClassLoader.java:687) at net.bytebuddy.dynamic.loading.ByteArrayClassLoader$ClassDefinitionAction.run(ByteArrayClassLoader.java:639) at java.base/java.security.AccessController.doPrivileged(AccessController.java:399) at net.bytebuddy.dynamic.loading.ByteArrayClassLoader.doPrivileged(ByteArrayClassLoader.java) at net.bytebuddy.dynamic.loading.ByteArrayClassLoader.findClass(ByteArrayClassLoader.java:406) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) at java.base/java.lang.Class.forName0(Native Method) at java.base/java.lang.Class.forName(Class.java:467) at net.bytebuddy.dynamic.loading.ByteArrayClassLoader.load(ByteArrayClassLoader.java:361) at net.bytebuddy.dynamic.loading.ClassLoadingStrategy$Default$WrappingDispatcher.load(ClassLoadingStrategy.java:367) at net.bytebuddy.dynamic.loading.ClassLoadingStrategy$Default.load(ClassLoadingStrategy.java:148) at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:101) at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:6325) at io.appium.java_client.proxy.Helpers.lambda$createProxy$0(Helpers.java:139) at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708) at io.appium.java_client.proxy.Helpers.createProxy(Helpers.java:118) at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:95) at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:70) at io.appium.java_client.pagefactory.AppiumFieldDecorator.proxyForAnElement(AppiumFieldDecorator.java:258) at io.appium.java_client.pagefactory.AppiumFieldDecorator$1.proxyForLocator(AppiumFieldDecorator.java:157) at org.openqa.selenium.support.pagefactory.DefaultFieldDecorator.decorate(DefaultFieldDecorator.java:61) at io.appium.java_client.pagefactory.AppiumFieldDecorator.decorate(AppiumFieldDecorator.java:196) at org.openqa.selenium.support.PageFactory.proxyFields(PageFactory.java:109) at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:101) at com.vodafone.automation.mobil.mva.pageobjects.login.LoginPage.(LoginPage.java:66) ... 61 more

The problem occurs when AppiumFieldDecorator is used.

Any solution or WA for this issue is appreciated. Thx!

update: The line that throws the exception is: return (new ByteBuddy()).subclass(cls).method(extraMethodMatcher == null ? matcher : matcher.and(extraMethodMatcher)).intercept(MethodDelegation.to(Interceptor.class)).defineField("methodCallListeners", MethodCallListener[].class, new ModifierContributor.ForField[]{Visibility.PRIVATE}).implement(new Type[]{HasMethodCallListeners.class}).intercept(FieldAccessor.ofBeanProperty()).make().load(ClassLoader.getSystemClassLoader(), Default.WRAPPER).getLoaded().asSubclass(cls); method:createProxy Class:io.appium.java_client.proxy.Helpers

AndrasFekete80 commented 2 months ago

The line that throws the exception is: return (new ByteBuddy()).subclass(cls).method(extraMethodMatcher == null ? matcher : matcher.and(extraMethodMatcher)).intercept(MethodDelegation.to(Interceptor.class)).defineField("methodCallListeners", MethodCallListener[].class, new ModifierContributor.ForField[]{Visibility.PRIVATE}).implement(new Type[]{HasMethodCallListeners.class}).intercept(FieldAccessor.ofBeanProperty()).make().load(ClassLoader.getSystemClassLoader(), Default.WRAPPER).getLoaded().asSubclass(cls); method:createProxy Class:io.appium.java_client.proxy.Helpers

It seems the problem is with the class loaders. If you replace the ClassLoader.getSystemClassLoader() with Helpers.class.getClassLoader() then it is working. Could you please add this modification to the next release?

mykola-mokhnach commented 2 months ago

@AndrasFekete80 Thanks for investigating this. Could you please create a PR?

vinothpandian18 commented 1 month ago

Thanks @AndrasFekete80 for fixing this issue. @mykola-mokhnach Any ETA, when this fix will be available in the next release as this is blocking to run my tests via Jenkins