JavaFX : Integrating Spring framework with JavaFX app(Incorrect configuration)

I am working on a JavaFX application and I would like to integrate Spring functionality with it. Currently the code compiles without any error, but when I request service layer methods which are tagged as @Transactional and @Service, I get NullPointerException. What am I doing wrong in the Spring configuration is what I dont understand. Here is my code for JavaFX :

Main class :

public class Main extends Application {

    private static final SpringFxmlLoader loader = new SpringFxmlLoader();

    @Override
    public void start(Stage stage) throws Exception {
       Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("login.fxml"));
        stage.setTitle("APPNAME");
        stage.setScene(new Scene(root, 300, 600));
        stage.setFullScreen(false);
        stage.setMaximized(false);
        stage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }

}


@Configuration
@EnableTransactionManagement
@ComponentScan(basePackages = {"packagename"})
public class ApplicationConfiguration {


    @Bean
    public PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer = new PropertySourcesPlaceholderConfigurer();
        Properties properties = new Properties();
        propertySourcesPlaceholderConfigurer.setProperties(properties);
        return propertySourcesPlaceholderConfigurer;
    }

    @Bean
    public MessageSource messageSource() {
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasenames("messages", "org.springframework.security.messages");
        messageSource.setUseCodeAsDefaultMessage(true);
        return messageSource;
    }
}

SpringLoader :

public class SpringFxmlLoader {

    private static final ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);

    public Object load(String url) {
        try (InputStream fxmlStream = SpringFxmlLoader.class
                .getResourceAsStream(url)) {
            System.err.println(SpringFxmlLoader.class
                    .getResourceAsStream(url));
            FXMLLoader loader = new FXMLLoader();
            loader.setControllerFactory(new Callback<Class<?>, Object>() {
                @Override
                public Object call(Class<?> clazz) {
                    return applicationContext.getBean(clazz);
                }
            });
            return loader.load(fxmlStream);
        } catch (IOException ioException) {
            throw new RuntimeException(ioException);
        }
    }
}

Now in my Controller, I have something like this :

@Component
public class Controller implements Initializable {
 @FXML
    public TextField usernameField;
    @FXML
    public PasswordField passwordField;
    @FXML
    public Button submitButton;
@Autowired
    private PersonService personService;
// Now the above personService throws me a NPE.
}

Am I somehow messing with Spring config for JavaFX. Kindly let me know. Thanks a lot. :-)

Update

After changes suggested by James D..I get the following error :

null
Exception in Application start method
Exception in thread "main" java.lang.RuntimeException: Exception in Application start method
    at com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:917)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication$152(LauncherImpl.java:182)
    at com.sun.javafx.application.LauncherImpl$$Lambda$2/1058634310.run(Unknown Source)
    at java.lang.Thread.run(Thread.java:745)
Caused by: java.lang.NullPointerException: inputStream is null.
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2459)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2429)
    at tooltank.MainClass.SpringFxmlLoader.load(SpringFxmlLoader.java:28)
    at tooltank.MainClass.Main.start(Main.java:15)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$159(LauncherImpl.java:863)
    at com.sun.javafx.application.LauncherImpl$$Lambda$57/667705538.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$172(PlatformImpl.java:326)
    at com.sun.javafx.application.PlatformImpl$$Lambda$53/767743416.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$null$170(PlatformImpl.java:295)
    at com.sun.javafx.application.PlatformImpl$$Lambda$55/1195477817.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$171(PlatformImpl.java:294)
    at com.sun.javafx.application.PlatformImpl$$Lambda$54/1403425489.run(Unknown Source)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
    at com.sun.glass.ui.gtk.GtkApplication.lambda$null$48(GtkApplication.java:139)
    at com.sun.glass.ui.gtk.GtkApplication$$Lambda$43/1429486634.run(Unknown Source)
    ... 1 more

Process finished with exit code 1

It happens in SpringFXMLLoader.java at following line :

 return loader.load(fxmlStream);

Answers


You have created a SpringFxmlLoader but you are not using it. You want

SpringFxmlLoader loader = new SpringFxmlLoader();
Parent root = (Parent) loader.load(getClass().getResource("login.fxml").toExternalForm());

instead of using the FXMLLoader directly.

I would actually write the SpringFxmlLoader differently, so that it matched the standard FXMLLoader API a little more closely:

public class SpringFxmlLoader {

    private static final ApplicationContext applicationContext = new AnnotationConfigApplicationContext(ApplicationConfiguration.class);

    public <T> T load(URL url) {
        try  {
            FXMLLoader loader = new FXMLLoader(url);
            loader.setControllerFactory(applicationContext::getBean);
            return loader.load();
        } catch (IOException ioException) {
            throw new RuntimeException(ioException);
        }
    }
}

Then your start method looks like:

SpringFxmlLoader loader = new SpringFxmlLoader();
Parent root = loader.load(getClass().getResource("login.fxml"));

You might need to tinker with the exact path to get things right, depending on your setup.


Need Your Help

Performance of MongoDB on VPS or cloud service not having mongoDB installed

php python mongodb vps

I have to build a web application which uses Python, php and MongoDB.

worklight app not working on real android phone

android jquery-mobile ibm-mobilefirst

I have developed a hybrid application in Ibm worklight using jquerymobile framework. The application accesses external database hosted on my own domain (www.blueocean5.com) through php script. It w...