Appium - PageFactory.initElements() does not initialise elements with @FindBy locators after integrating Spring Dependency Injection

I'm trying to integrate Spring Dependency Injection into our Appium test automation framework such that I can inject instance of WebDriver into any PageObject automatically. This has worked well so far except the fact that PageFactory.initElements(new AppiumFieldDecorator(driver),pageObjectClassInstance); does not decorate elements with the locator annotations. Instead it simply decorates them with id as the element variable name, which I guess is the fallback strategy.

I get an instance of WebDriver using a WebDriverRunner class in the following manner:

package com.org.core;

import com.org.listener.ElementListener;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.events.EventFiringWebDriverFactory;
import io.appium.java_client.events.api.Listener;
import io.appium.java_client.ios.IOSDriver;
import io.github.bonigarcia.wdm.WebDriverManager;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

@Component
public class WebDriverRunner {

  private WebDriver driver;
  private static final Logger LOG = LoggerFactory.getLogger(WebDriverRunner.class);

  public void initWebDriver(TestConfiguration configuration) throws MalformedURLException {
    LOG.info("Initialising web driver");

    if (configuration.isWeb()) {
      WebDriverManager.chromedriver().setup();
      ChromeOptions options = new ChromeOptions();
      if (configuration.isHeadless()) {
        options.addArguments("--headless");
      }
      driver = new ChromeDriver(options);
      driver.navigate().to(configuration.getBaseUrl());
    } else {
      String appiumUrl = System.getProperty("appium_url");
      if (System.getProperty("platform_name").equals("android")) {
        driver = new AndroidDriver(new URL(appiumUrl), configuration.getCapabilities());
      } else {
        driver = new IOSDriver(new URL(appiumUrl), configuration.getCapabilities());
      }
    }
    // Adding event listeners
    List<Listener> listeners = new ArrayList<>();
    listeners.add(new ElementListener());
    driver = EventFiringWebDriverFactory.getEventFiringWebDriver(driver, listeners);

  }

  public WebDriver getWebDriver() {
    return driver;
  }

}

This is my Spring Context class:

package com.org.core;

import com.org.listener.ElementListener;
import com.org.registry.PageObjectRegistry;
import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.events.EventFiringWebDriverFactory;
import io.appium.java_client.events.api.Listener;
import io.appium.java_client.ios.IOSDriver;
import io.github.bonigarcia.wdm.WebDriverManager;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;

@Configuration
@ComponentScan(basePackages = "com.org")
public class SpringContext {

  private static final Logger LOG = LoggerFactory.getLogger(SpringContext.class);

  @Autowired
  public TestConfiguration configuration;

  @Autowired
  public PageObjectRegistry pageObjectRegistry;

  @Autowired
  public WebDriverRunner driverRunner;


  @Bean @Lazy(true)
  public WebDriver getDriver() {
     return driverRunner.getWebDriver();
  }

}

I have a PageObjectRegistry class which returns instances of pageobjects based on platform the tests are running on (iOS, Android etc). It has a method named get() which returns an instance of a PageObject. Please note that it is in this method that I perform PageFactory.initElements();

package com.org.registry;

import com.org.core.Platform;
import com.org.pages.BasePage;
import io.appium.java_client.pagefactory.AppiumFieldDecorator;
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner;
import org.apache.commons.collections4.map.LinkedMap;
import org.apache.commons.collections4.map.MultiKeyMap;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.PageFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

/**
 * Registry for page objects
 *
 * <p>The registry holds a map of page objects by page and platform. E.g. get(LoginPage.class,
 * Platform.ANDROID) will return the Android page object for the login page.
 *
 * <p>The registry can be initialised one page object at a time ({@link #register(Class)}) or by
 * scanning certain packages on the classpath ({@link #initialiseFromClasspath(String[])}).
 */
@Component
public class PageObjectRegistry implements ApplicationContextAware {

  /**
   * Fetch an instance of a page object class from the registry.
   *
   * @param <T> type of page object
   * @param clazz type to look for
   * @param platform platform to look for
   * @param driver {@link WebDriver}
   * @return instance of the corresponding page object class
   */
  public <T extends BasePage> T get(Class<T> clazz, Platform platform, WebDriver driver) {
    Class<T> registeredClass = (Class) registry.get(clazz, platform);
    if (registeredClass == null) {
      LOG.warn(
          "Could not find a page object for key {}|{}. Returning null",
          clazz.getName(),
          platform.name());
      return null;
    }
    LOG.info(
        "Returning instance of {} for key {}|{}",
        registeredClass.getName(),
        clazz.getName(),
        platform.name());

    String className = registeredClass.getName();
    String beanName = className.substring(className.lastIndexOf(".")+1);
    char[] chArr = beanName.toCharArray();
    chArr[0] = Character.toLowerCase(chArr[0]);
    T page = (T) applicationContext.getBean(new String(chArr));
    PageFactory.initElements(new AppiumFieldDecorator(driver),page);
    return page;
  }


  @Override
  public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
    this.applicationContext = applicationContext;
  }
}

Now, wherever I need to use an instance of WebDriver, I have autowired the driver variable in BasePage like this:

@Autowired @Lazy
protected WebDriver driver;

Let's say there is a PageObject class LoginPage:

@Component
public class LoginPage extends BasePage {

  @iOSFindBy(accessibility = "login_page_username_text_field")
  @AndroidFindBy(
      uiAutomator = "new UiSelector().className(\"android.widget.EditText\").instance(0)")
  @FindBy(id = "USER_NAME")
  private WebElement usernameField;

  @iOSFindBy(accessibility = "login_page_password_text_field")
  @AndroidFindBy(
      uiAutomator = "new UiSelector().className(\"android.widget.EditText\").instance(1)")
  @FindBy(id = "PASSWORD")
  private WebElement passwordField;

  @iOSFindBy(accessibility = "login_page_login_button")
  @AndroidFindBy(id = appPackage + ":id/login_page_login_button")
  @FindBy(xpath = "//span[text()='Log in']")
  private WebElement loginButton;

  @iOSXCUITFindBy(iOSNsPredicate = "name == 'done'")
  @AndroidFindBy(id = appPackage + ":id/action_signin")
  private WebElement reccomendationDone;

  @iOSFindBy(accessibility = "Allow")
  private WebElement allowNotification;

  @iOSFindBy(accessibility = "Notify me of chats")
  private WebElement receiveAlertsChat;

  /** Login with username and password. */
  public HomePage login(String username, String password) throws InterruptedException {
    //code for the method here
    return page(HomePage.class);
  }
  }

Now whenever the get() method in PageObjectRegistry is called to fetch PageObject instance, it fetches an instance of a PageObject but PageFactory.initElements() does not decorate the webelements in the page with the locators in the @FindBy annotation. Instead it gets decorated with variable name as the id. I am not sure why. Could someone please help. Many Thanks!