Pull to refresh

Comments 20

Чем обусловлена обязательная инициализация в потоке UI?
Возможно, стоит инициализировать в стороннем потоке, а потом обращатся вызовами?
Хороший вопрос, ждал его.

На самом деле концептуально Вы не обязаны инициализировать спринг контекст в UI потоке, но это избавит Вас от проблем. Так, например, если на момент инициализации бинов спринга Вы будете взаимодействовать с UI, Вы получите труднопредсказуемые ошибки. Если посмотреть на пример из статьи, то MainController#init() либо вывалится с исключениями, либо просто уйдет в дедлок. Именно поэтому я настоятельно рекомендую инициализировать спринг контекст в UI потоке. Ну а если какая-то инициализация требует дополнительного времени, то лучше точечно выносить ее в другой поток.
Почему deadlock? там же npe будет(.
И вроде как обязаны использовать в том же потоке, поскольку все контроллеры и вьюхи должны быть уже в контексте Spring и Fx должен работать уже с проинициализированными в Spring объектами. Иначе просто не получится.
Почему NPE? В каком месте? Если в классе Application, то да. Но само собой, нужно следить за порядком инициализации, и в таком случае концептуально менять архитектуру описанного примера.

А вот любое взаимодействие с UI не из UI потока — это ошибка априори, за исключением тех случаев, в которых взаимодействие с UI обернуто в Platform.runLater(...);.
Я наверное не правильно выразился, поскольку maincontroller вы получить без уже созданного контекста не сможете. Т.е. скорее всего если и обернете context = SpringApplication.run(getClass(), savedArgs); в другой поток, то
getBean exception кинет при попытке отрисовать MainView. Кстати я не совсем понял, почему у вас и View не в контексте? У fx можно же factory переделать.
поскольку maincontroller вы получить без уже созданного контекста не сможете. Т.е. скорее всего если и обернете context = SpringApplication.run(getClass(), savedArgs); в другой поток, то
getBean exception кинет при попытке отрисовать MainView

Все верно. NPE скорее всего выбросится в Application классе, при вызове view.getParent(). Как я писал выше нужно следить за порядком инициализации, и в таком случае концептуально менять архитектуру описанного примера.

Кстати я не совсем понял, почему у вас и View не в контексте? У fx можно же factory переделать.

А вот тут я не понял вопрос.
А не может получится ситуации, когда спринг контекст просто повесит UI? (простите, у меня нет опыта в работе со Spting Boot)
Сам по себе спринг — исключено. А вот если при инициализации Ваших бинов происходят длительные операции в UI потоке, то приложению потребуется завершить для начала все операции, и только потом появится пользовательский интерфейс. Как писал выше — длительные операции инициализации лучше точечно переводить в другой поток.

А вообще, обязательно попробуйте Spring Boot — лучший Java фреймворк современности, по моему мнению.
Раз уж вы тут, если не сложно, ответьте пожалуйста на нестолько вопросов:
— Имеет ли смысл использовать Spring Boot, если у вас приложение не использует базы данных и DI ему совсем не нужен?
— Существует ли возможность как-то делать конфигурационные класы (настройки которых бы автоматически сохранялись и загружались с файла)?
С удовольствием.

Имеет ли смысл использовать Spring Boot, если у вас приложение не использует базы данных и DI ему совсем не нужен?

Это Вам решать, интеграция со Spring Boot — дело, скорее, добровольное. Spring Framework сам по себе предоставляет массу полезных вещей, которые Вы можете внедрить в клиентское приложение. Например, тот же Spring Security. Но если Вы прекрасно обходитесь без него — почему нет?

Существует ли возможность как-то делать конфигурационные класы (настройки которых бы автоматически сохранялись и загружались с файла)?

Вам придется хранить файл настроек где-нибудь. Смотрите в сторону java.util.Properties, обычно используют именно его (методы load(..) и store(...)).
Спасибо большое за ваши ответы
Я правильно понимаю, что все вью и их контроллеры придётся прописывать в конфигурацию руками?
Также хороший вопрос, спасибо.

Если следовать примеру из статьи — да, но Вы можете написать базовый класс для контроллеров, с конструктором по умолчанию, который будет регистрировать контроллер в спринг контексте, и подгружать все необходимые бины. Смотрите в сторону org.springframework.context.ApplicationContextAware (статическим методом Вы будете получать контекст спринга). Но необходимо учесть, что спринг контекст, в данном случае, должен инициализироваться раньше, чем Вы соберетесь использовать FXML загрузчик.
Может глупый вопрос спрошу: а вообще-то на JavaFx кто-то сейчас пишет в промышленных масштабах?
Трудно сказать. Но я сейчас работаю в билетном агенстве, и мы успешно внедрили сервис билетопечати на JavaFX.
Так же можно попробовать перейти с maven на gradle.
Этапа адаптации достаточно короткий.
Но работа с ним намного прозрачнее и удобнее (это IMHO, но слышал это от многих).
Кстати да, спасибо, обязательно попробую! Gradle — новый тренд сборки Java проектов, который, кстати, вполне перспективен.
Нам обязательно необходимо инициализировать Spring контекст в UI потоке (в том же потоке, что и JavaFX).

JavaDoc к методу javafx.application.Application.init():
NOTE: This method is not called on the JavaFX Application Thread.

Т.е. у вас все равно контекст спринга инициализируется не в потоке JavaFX UI.
Да, действительно, я допустил ошибку в примере (класс AbstractJavaFxApplicationSupport.java). Метод init() вызывается не в UI потоке, и если Вам потребуется создать экземпляры типов Scene, Stage, открыть popup, то вы получите ошибку на момент инициализации. Поэтому я рекомендую запускать инициализацию Spring контекста в методе start(), он как раз из UI вызывается.

В текущем примере в процессе инициализации создаются лишь JavaFX компоненты, да инициализируются контроллеры, поэтому проблем не возникло.

Большое спасибо за замечание, сейчас внесу правки.
Sign up to leave a comment.

Articles