0

I have an application with multiple controllers and Stages. I have tried to implement a switchable theme system via CSS in a parent controller class all my other controllers inherit from. It works fine, except when I open my Preferences dialog and close it. If i try to change themes after that, i get an infinite stream of NullPointerExceptions in the console, and my app stops responding. It is also important to note that this DOES NOT happen if i run it through IntelliJ, only if I run my jar.

Lots of relevant code and dumps:

    public class ControllerBase {

  protected static final String LOGGING_CONFIG_FILE_NAME = "/config/logging/log4j.xml";

  public static SimpleStringProperty themeFilename = new SimpleStringProperty(  );

  protected Stage stage;

  protected String cfgFile = new WorkbenchAppConfig().getFileName();
  protected AppPropertiesManager prefs = new AppPropertiesManager();

  protected Logger log;
  protected ResourceBundle res;

  protected ChangeListener CSSListener;

  protected ControllerBase(){


    doInitsFromConfigFile();


    String themeName = prefs.getString( cfgFile, KEY_GUI_THEME_ACTIVE, "Light" );
    themeFilename.set(  prefs.getString( cfgFile, KEY_GUI_THEMES_BASE + "." + themeName + ".filename" ));



    CSSListener = new ChangeListener() {
      @Override
      public void changed( ObservableValue observable, Object oldValue, Object newValue ) {
        updateCss();
      }
    };
    themeFilename.addListener( CSSListener );

  }

  protected void updateCss() {

    //Refresh Theme settings
    if(stage != null) {
      ObservableList< String > css = stage.getScene().getStylesheets();
      css.clear();
      css.add( themeFilename.getValue() );
    }
  }

  protected void doInitsFromConfigFile() {

    // get localized resources
    String localeLanguage = prefs.getString(cfgFile, KEY_APP_LOCALE_LANGUAGE, "en");
    String localeCountry = prefs.getString(cfgFile, KEY_APP_LOCALE_COUNTRY, "US");


    res = CommonGuiUtils.getStringResourceBundle();

    // get active GUI theme
    String themeName = prefs.getString( cfgFile, KEY_GUI_THEME_ACTIVE, "Dark" );
    themeFilename.set(  prefs.getString( cfgFile, KEY_GUI_THEMES_BASE + "." + themeName + ".filename" ));
  }

Methods from my main controller to handle the selection menu:

private void setUpThemeSelection() {

    lightingStyleGroup = new ToggleGroup();
    lightingStyleGroup.getToggles().add( lightThemeOption );
    lightingStyleGroup.getToggles().add( darkThemeOption );

    String themeName = prefs.getString( cfgFile, KEY_GUI_THEME_ACTIVE, "Dark" );
    ObservableList list = lightingStyleGroup.getToggles();

    for ( Object x : list ) {
      if ( ( (RadioMenuItem) x ).getText().startsWith( themeName ) ) {
        lightingStyleGroup.selectToggle( (Toggle) x );
      }
    }
  }

   private void switchTheme( ActionEvent actionEvent ) {

    //Find selected item and change prefs
    RadioMenuItem selected = (RadioMenuItem) lightingStyleGroup.getSelectedToggle();
    prefs.setString( cfgFile, KEY_GUI_THEME_ACTIVE, selected.getText() );

    //Refresh Theme settings
    String themeName = prefs.getString( cfgFile, KEY_GUI_THEME_ACTIVE, "Dark" );
    themeFilename.set(  prefs.getString( cfgFile, KEY_GUI_THEMES_BASE + "." + themeName + ".filename" ));

  }

Dump from console, abridged

Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at com.sun.javafx.css.StyleManager.lambda$loadStylesheetUnPrivileged$191(StyleManager.java:1060)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.css.StyleManager.loadStylesheetUnPrivileged(StyleManager.java:1054)
    at com.sun.javafx.css.StyleManager.loadStylesheet(StyleManager.java:935)
    at com.sun.javafx.css.StyleManager.processStylesheets(StyleManager.java:1556)
    at com.sun.javafx.css.StyleManager.gatherSceneStylesheets(StyleManager.java:1625)
    at com.sun.javafx.css.StyleManager.findMatchingStyles(StyleManager.java:1663)
    at javafx.scene.CssStyleHelper.createStyleHelper(CssStyleHelper.java:111)
    at javafx.scene.Node.reapplyCss(Node.java:8985)
    at javafx.scene.Node.impl_processCSS(Node.java:9182)
    at javafx.scene.Parent.impl_processCSS(Parent.java:1249)
    at javafx.scene.Node.processCSS(Node.java:9058)
    at javafx.scene.Scene.doCSSPass(Scene.java:545)
    at javafx.scene.Scene.access$3600(Scene.java:159)
    at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2392)
    at com.sun.javafx.tk.Toolkit.lambda$runPulse$30(Toolkit.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:354)
    at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:381)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
    at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$404(QuantumToolkit.java:319)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:748)
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at com.sun.javafx.css.StyleManager.lambda$loadStylesheetUnPrivileged$191(StyleManager.java:1060)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.css.StyleManager.loadStylesheetUnPrivileged(StyleManager.java:1054)
    at com.sun.javafx.css.StyleManager.loadStylesheet(StyleManager.java:935)
    at com.sun.javafx.css.StyleManager.processStylesheets(StyleManager.java:1556)
    at com.sun.javafx.css.StyleManager.gatherSceneStylesheets(StyleManager.java:1625)
    at com.sun.javafx.css.StyleManager.findMatchingStyles(StyleManager.java:1663)
    at javafx.scene.CssStyleHelper.createStyleHelper(CssStyleHelper.java:111)
    at javafx.scene.Node.reapplyCss(Node.java:8985)
    at javafx.scene.Node.impl_processCSS(Node.java:9182)
    at javafx.scene.Parent.impl_processCSS(Parent.java:1249)
    at javafx.scene.Node.processCSS(Node.java:9058)
    at javafx.scene.Scene.doCSSPass(Scene.java:545)
    at javafx.scene.Scene.access$3600(Scene.java:159)
    at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2392)
    at com.sun.javafx.tk.Toolkit.lambda$runPulse$30(Toolkit.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:354)
    at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:381)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
    at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$404(QuantumToolkit.java:319)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:748)
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException
    at com.sun.javafx.css.StyleManager.lambda$loadStylesheetUnPrivileged$191(StyleManager.java:1060)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.css.StyleManager.loadStylesheetUnPrivileged(StyleManager.java:1054)
    at com.sun.javafx.css.StyleManager.loadStylesheet(StyleManager.java:935)
    at com.sun.javafx.css.StyleManager.processStylesheets(StyleManager.java:1556)
    at com.sun.javafx.css.StyleManager.gatherSceneStylesheets(StyleManager.java:1625)
    at com.sun.javafx.css.StyleManager.findMatchingStyles(StyleManager.java:1663)
    at javafx.scene.CssStyleHelper.createStyleHelper(CssStyleHelper.java:111)
    at javafx.scene.Node.reapplyCss(Node.java:8985)
    at javafx.scene.Node.impl_processCSS(Node.java:9182)
    at javafx.scene.Parent.impl_processCSS(Parent.java:1249)
    at javafx.scene.Node.processCSS(Node.java:9058)
    at javafx.scene.Scene.doCSSPass(Scene.java:545)
    at javafx.scene.Scene.access$3600(Scene.java:159)
    at javafx.scene.Scene$ScenePulseListener.pulse(Scene.java:2392)
    at com.sun.javafx.tk.Toolkit.lambda$runPulse$30(Toolkit.java:355)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.Toolkit.runPulse(Toolkit.java:354)
    at com.sun.javafx.tk.Toolkit.firePulse(Toolkit.java:381)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:510)
    at com.sun.javafx.tk.quantum.QuantumToolkit.pulse(QuantumToolkit.java:490)
    at com.sun.javafx.tk.quantum.QuantumToolkit.lambda$runToolkit$404(QuantumToolkit.java:319)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:748)

    ...and so on forever

Does anyone know whats going on? Whats causing this?

ScarySpider
  • 139
  • 5
  • Possible duplicate of [What is a NullPointerException, and how do I fix it?](https://stackoverflow.com/questions/218384/what-is-a-nullpointerexception-and-how-do-i-fix-it) – Jérôme Apr 04 '18 at 22:44
  • 1
    What is the stylesheet value being changed to? Is the appropriate stylesheet in the jar file in the expected location? – James_D Apr 04 '18 at 23:03
  • @James_D the correct file name as far as i can tell and yes it is packaged in the jar – ScarySpider Apr 04 '18 at 23:05

1 Answers1

0

I found the problem, my preferences manager was returning null sometimes (seemingly randomly) at just the wrong time. I have worked around the problem.

ScarySpider
  • 139
  • 5