Skip to content

IllegalArgumentException when calling PageFactory.initElements(new AppiumFieldDecorator(androidDriver), this) #1100

@bill2605

Description

@bill2605

The problem

When trying to init PageObjects classes with annotations like AndroidFindBy, i am unable to get past the PageFactory.initElements(new AppiumFieldDecorator(androidDriver), this). Test will fail with illegal argument exception and not much details as to which argument is invalid and why.

Environment

appium version: 1.10.1
appium java client: 7.0.0
node ver: v9.10.1
android im: pixel 2 xl api 27
desktop: mac (latest)

Link to Appium logs

Appium log: https://gist.github.com/bill2605/583f868e59f7852f4aebfc42f942c6cd

Code To Reproduce Issue

Note that i am using Spring for my framework. That being said below is the code to initialize an AndroidDriver to be used by the pageObjects.

`@Service
@Profile("android")
public class AndroidDriverLoader {

private final Logger logger = LoggerFactory.getLogger(AndroidDriverLoader.class);

@Resource
protected ConfigProperty configProperty;

public AndroidDriver<AndroidElement> driver;
private AppiumDriverLocalService appiumDriverLocalService;

@PostConstruct
public void androidDriverLoaderInit() {
    loadDriver();
}

/**
 * load the specific android driver based on reference
 */
private void loadDriver() {
    final DesiredCapabilities desiredCapabilities = new DesiredCapabilities();

    if (Objects.equals(configProperty.getMobileType(), "emulator")) {
        desiredCapabilities.setCapability(AndroidMobileCapabilityType.AVD, configProperty.getAndroidAvd());
        desiredCapabilities.setCapability(MobileCapabilityType.APP, configProperty.getAndroidApp());

        appiumDriverLocalService = getDefaultAppiumLocalService();
        appiumDriverLocalService.start();

        driver = new AndroidDriver<>(appiumDriverLocalService, getDefaultAndroidCapabilities().merge(desiredCapabilities));
    } 
}

private DesiredCapabilities getDefaultAndroidCapabilities() {
    final DesiredCapabilities desiredCapabilities = new DesiredCapabilities();
    desiredCapabilities.setCapability(MobileCapabilityType.AUTOMATION_NAME, AutomationName.ANDROID_UIAUTOMATOR2);
    desiredCapabilities.setCapability(MobileCapabilityType.PLATFORM_NAME, Platform.ANDROID);
    desiredCapabilities.setCapability(MobileCapabilityType.DEVICE_NAME, configProperty.getAndroidDeviceName());
    desiredCapabilities.setCapability(AndroidMobileCapabilityType.NO_SIGN, true);
    desiredCapabilities.setCapability(MobileCapabilityType.FULL_RESET, false);
    desiredCapabilities.setCapability(MobileCapabilityType.NO_RESET, true);
    desiredCapabilities
            .setCapability(MobileCapabilityType.NEW_COMMAND_TIMEOUT, Integer.parseInt(configProperty.getCommandTimeOut()));

    return desiredCapabilities;
}

/**
 * return default appium local service
 *
 * @return {@link AppiumDriverLocalService}
 */
private AppiumDriverLocalService getDefaultAppiumLocalService() {
    return new AppiumServiceBuilder()
            .usingDriverExecutable(Paths.get(configProperty.getAppiumDriverExecutable()).toFile())
            .withAppiumJS(Paths.get(configProperty.getAppiumJs()).toFile())
            .withIPAddress(configProperty.getServiceIPAddress())
            .usingPort(Integer.parseInt(configProperty.getAppiumPort()))
            .withArgument(GeneralServerFlag.LOCAL_TIMEZONE)
            .build();
}

public AndroidDriver<AndroidElement> getDriver() {
    return driver;
}`

Each PageObject extends AndroidAbstractView
which holds the following information:
`@Service
@Profile("android")
public abstract class AndroidAbstractView implements RemoteElementUtils {

private final Logger logger = LoggerFactory.getLogger(AndroidAbstractView.class);

@Resource
protected AndroidDriverLoader androidDriverLoader;
@Resource
protected ConfigProperty configProperty;

protected static AppiumDriver androidDriver;

private String iconLoadingId = "item_loading_view";
private String loadingViewRefreshXpath = "//android.view.ViewGroup[contains(@resource-id, 'id/swipe_refresh_layout')]/android.widget.ImageView";

@PostConstruct
protected abstract void init();

Note that RemoteElementUtils is just an interface for all findElementby, waitForVisibible to be implemented for Web, Android and IOS (nothing fancy there)

PageObject is as follow:
`@Service
@Profile("android")
public class LoginView extends AndroidAbstractView {

@AndroidFindBy(xpath = "//*[contains(@resource-id, 'login_username_auto_complete_text_view')]")
protected AndroidElement inputUserName;
@AndroidFindBy(xpath = "//*[contains(@resource-id, 'login_next_button')]")
protected AndroidElement buttonContinue;
@AndroidFindBy(xpath = "//*[contains(@resource-id, 'login_password_edit_text')]")
protected AndroidElement inputPassword;
@AndroidFindBy(xpath = "//*[contains(@resource-id, 'login_password_log_in_button')]")
protected AndroidElement buttonLogin;
@AndroidFindBy(id = "login_username_dev_stuff_button")
protected AndroidElement buttonDevStuff;
@AndroidFindBy(id = "def_stuff_api_base_url_edit_text")
protected AndroidElement inputApiEndPointUrl;
@AndroidFindBy(id = "def_stuff_api_base_url_button")
protected AndroidElement buttonApply;

@PostConstruct
public void init()
{
    this.androidDriver = androidDriverLoader.getDriver();
    PageFactory.initElements(new AppiumFieldDecorator(androidDriver), this);
}

public void login(final String userName, final String password) {...}`

When running a test for android, using debugger i see that the driver is created and ready to be used. but whenever it reaches PageFactory.initElements(new AppiumFieldDecorator(androidDriver), this);

the following error is returned:
Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loginView': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException Exception in thread "main" java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:124) at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:83) at cucumber.runtime.java.spring.CucumberTestContextManager.getContext(SpringFactory.java:247) at cucumber.runtime.java.spring.CucumberTestContextManager.<init>(SpringFactory.java:239) at cucumber.runtime.java.spring.SpringFactory.start(SpringFactory.java:132) at cucumber.runtime.java.JavaBackend.buildWorld(JavaBackend.java:114) at cucumber.runner.Runner.buildBackendWorlds(Runner.java:120) at cucumber.runner.Runner.runPickle(Runner.java:38) at cucumber.runtime.Runtime$1.run(Runtime.java:84) at cucumber.runtime.Runtime$SameThreadExecutorService.execute(Runtime.java:220) at cucumber.runtime.Runtime.run(Runtime.java:81) at cucumber.api.cli.Main.run(Main.java:26) at cucumber.api.cli.Main.main(Main.java:8) Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'loginView': Invocation of init method failed; nested exception is java.lang.IllegalArgumentException at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:139) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyBeanPostProcessorsBeforeInitialization(AbstractAutowireCapableBeanFactory.java:419) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1736) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:576) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:498) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318) at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199) at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:848) at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:865) at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:548) at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:128) at org.springframework.test.context.support.AbstractGenericContextLoader.loadContext(AbstractGenericContextLoader.java:60) at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.delegateLoading(AbstractDelegatingSmartContextLoader.java:108) at org.springframework.test.context.support.AbstractDelegatingSmartContextLoader.loadContext(AbstractDelegatingSmartContextLoader.java:251) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContextInternal(DefaultCacheAwareContextLoaderDelegate.java:98) at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:116) ... 12 more Caused by: java.lang.IllegalArgumentException at net.sf.cglib.asm.ClassReader.<init>(Unknown Source) at net.sf.cglib.asm.ClassReader.<init>(Unknown Source) at net.sf.cglib.asm.ClassReader.<init>(Unknown Source) at net.sf.cglib.proxy.BridgeMethodResolver.resolveAll(BridgeMethodResolver.java:61) at net.sf.cglib.proxy.Enhancer.emitMethods(Enhancer.java:911) at net.sf.cglib.proxy.Enhancer.generateClass(Enhancer.java:498) at net.sf.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) at net.sf.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:216) at net.sf.cglib.proxy.Enhancer.createHelper(Enhancer.java:377) at net.sf.cglib.proxy.Enhancer.create(Enhancer.java:304) at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:55) at io.appium.java_client.pagefactory.utils.ProxyFactory.getEnhancedProxy(ProxyFactory.java:33) at io.appium.java_client.pagefactory.AppiumFieldDecorator.proxyForAnElement(AppiumFieldDecorator.java:217) at io.appium.java_client.pagefactory.AppiumFieldDecorator.access$0(AppiumFieldDecorator.java:215) at io.appium.java_client.pagefactory.AppiumFieldDecorator$1.proxyForLocator(AppiumFieldDecorator.java:107) at org.openqa.selenium.support.pagefactory.DefaultFieldDecorator.decorate(DefaultFieldDecorator.java:62) at io.appium.java_client.pagefactory.AppiumFieldDecorator.decorate(AppiumFieldDecorator.java:155) at org.openqa.selenium.support.PageFactory.proxyFields(PageFactory.java:113) at org.openqa.selenium.support.PageFactory.initElements(PageFactory.java:105) at com.workjam.platform.frontend.android.view.LoginView.init(LoginView.java:35) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleElement.invoke(InitDestroyAnnotationBeanPostProcessor.java:363) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor$LifecycleMetadata.invokeInitMethods(InitDestroyAnnotationBeanPostProcessor.java:307) at org.springframework.beans.factory.annotation.InitDestroyAnnotationBeanPostProcessor.postProcessBeforeInitialization(InitDestroyAnnotationBeanPostProcessor.java:136) ... 29 more

When attempting to debug code i made it all the way to method from io.appium.java_client.pagefactory.utils.ProxyFactory;

public static <T> T getEnhancedProxy(Class<T> requiredClazz, Class<?>[] params, Object[] values, MethodInterceptor interceptor) { Enhancer enhancer = new Enhancer(); enhancer.setSuperclass(requiredClazz); enhancer.setCallback(interceptor); return (T) enhancer.create(params, values); }

and crash occurs at return (T) enhancer.create(params, values);

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions