Всем привет. Меня зовут Тетка Андрей, и я работаю в качестве Java Backend Developer в компании CodeValue в Израиле. Моя основная обязанность - разработка BackEnd на Java. Время от времени я делаю свои "Pet Projects", которые позволяют мне проверить свои навыки и испытать себя в новых технологиях. Недавно я решил попробовать свои силы с последней версией Spring Boot v3 и некоторыми другими технологиями. В итоге получилось кое что интересное, и я решил попробовать сделать отдельное приложение. Однако, я столкнулся с некоторыми проблемами при создании и дистрибьюции Java приложений. В этой статье я расскажу о том, как я разрабатывать Desktop-приложения на Java с Spring Boot.  До начала необходимо оговориться о некоторых деталях. Я не являюсь профессиональным разработчиком Desktop-приложений и первый раз решил попробовать себя в этой области. Следовательно, могут возникнуть идеологические или практические неточности. Моя цель - дать понятное руководство для тех, кто сталкнётся с аналогичными трудностями. Лично мне его не хватало. Вы можете выбрать другой путь решения проблемы. Создать инсталлятор который установит все зависимости или просто создать скрипт который установит все зависимости. Всё зависит от потребностей. Давайте начнем с основ.  Важно знать, что Java не является лучшим языком для разработки интерфейсов пользовательского интерфейса. Хотя концепция "написано один раз, работает везде" привлекательна, есть некоторые ограничения, которые следует учитывать. JVM долго запускается и при запуске код работает в режиме интерпретатора, что конечно влияет на производительность. По этому Джаву чаще используют именно на backend, что бы пользоваться быстрой Джавой, которую скомпилирует JIT compiler. Так же использовать Spring в приложении которое запускается как Desktop Application тоже не лучшее решение, Spring хоть и удобен, но может долго подниматься при запуске. В пустом приложении это занимает секунды, а если мы добавим работу с базой данных(H2), различные сервисы, то не удивительно если приложение будет подниматься уже минуты. Так же стоит помнить что у пользователей нашего приложения может быть различные компьютеры, на одном приложение может подниматься за 10 секунд, а на другом за 50 и это будет вполне нормальная ситуация. Но раз уж изначально это был эксперимент, то давайте начнём создавать наше приложение. Для начала давайте создадим Spring Boot проект. Для этого идём на https://start.spring.io/ и выбираем то что нам нужно.После генерации проекта мы получаем стандартный файл для запуска Spring boot в приложении. Spring может запускаться от нескольких секунд до нескольких минут, всё конечно же зависит от размера проекта. Чтобы улучшить пользовательский опыт, необходимо изменить последовательность и в первую очередь отобразить интерфейс (GUI), который покажет, что приложение загружается. Давайте перейдём к выбору GUI фреймворка для нашего приложения.  Первый вариант который я начал рассматривать, это написать отдельное приложение для GUI интерфейса на более подходящем для этого языке. Это приложение уже скачало бы JVM при необходимости и управляло бы моим приложение. Я рассмотрел 4 варианта: Flutter - относительно новая разработка от Google, применяется для создания мобильных и десктопных кросплатформенных приложений. Но минимальное приложение, с пустой формой весило 100Мб, даже при отключении всех дебаг функций не удалось сильно сократить размер приложения GoLang - не самый очевидный вариант для GUI интерфейса и не самый правильный, но в целом довольно интересный. Правда скомпилированный пустой аппликейшн опять весил 50+ Мегабайт и даже не запустился C++ QT - QT наверное является одним из самых основных фреймворков для создания приложения и он всем хорош Кроссплатформенность - есть Возможность создать красивый интерфейс - есть Выходной файл весил всего 80Кб, а туда я даже добавил кнопку чего я не позволял себе во Flutter и GoLang Есть Scene Builder где мы можем просто перетаскивать кнопочки и тем самым создавать красивый интерфейс Но был и один недостаток, а именно C++. Всё таки плюсы это сложнее и не так приятны для разработки. А так как был чисто не коммерческий проект, то не хотелось сильно запариваться с этим всем Python QT - Так как мне понравился QT, изначально не хотел его пробовать так как этот фреймворк уже довольно старый, но не понравился именно C++, то решил попробовать его с Python. И тут было всё замечательно, но у пользователя может не оказаться Python и тогда прийдётся его просить устанавливать и его, что не очень приятно В итоге попробовав способ с полным разделением визуала и функционала меня не устроило и пришлось выбирать Java UI Framework. А выбирать действительно есть из чего. Я при разработке выбрал JavaFX, как наиболее подходящий и функциональный GUI фреймворк для Java, но меня ждало несколько неприятностей.  JavaFX — платформа на основе Java для создания приложений с насыщенным графическим интерфейсом. Она может использоваться для создания настольных приложений, запускаемых непосредственно из под операционных систем, интернет-приложений, работающих в браузерах, а также приложений для мобильных устройств. JavaFX предназначена для замены ранее используемой библиотеки Swing. JavaFX очень быстро ворвался в JDK 8, но так же быстро оттуда и выпилился. Начиная с версии Java 11 больше не входит в Java SE и не разрабатывается компанией Oracle (как отдельный модуль поддерживается компанией Gluon). В целом JavaFX во всём хорош, но то что его нет больше в составе JRE, это печально. Но временами без танцев с бубнами не обойтись и не всегда всё работает гладко. Например, могут быть различные проблемы на процессорах Apple M1, а на Windows x64 всё будет работать без проблем. Так что, если вы планируете создать совсем простой GUI "с одной кнопкой", то лучше выбрать Swing. И так приступим. Давайте переделаем наше приложение, чтобы при запуске отображалось окно загрузки пока инициализируется Spring. Для начала подключим зависимости. Я сгенерировал Gradle проект, по этому буду использовать код для Gradle в примерах ниже. Также я пользуюсь новым интерфейсом IntelliJ Idea и скриншоты будут с новым интерфейсом, но думаю разобраться не составит труда. Подключаем плагин gradle Так же в build.gradle добавляем конфигурацию для нашего приложения Скачиваем JavaFX SDK: https://gluonhq.com/products/javafx/  После распаковки нужно подключить SDK к нашей IDE. Для этого идём в настройки проекта и подключаем библиотеку Далее выбираем что хотим добавить библиотеку Java и указываем путь к папке куда вы распаковали SDK  Ну и остался последний момент. Нужно подключить нашу библиотеку к проекту. Для этого идём в модули, выбираем наш проект и добавляем зависимость После этого остаётся ещё одно действие. Нам нужно добавить несколько параметров при запуске нашего приложения.  Нам нужно добавить параметры для виртуальной машины. По умолчанию они не отображаются, найти их можно в меню More Options -> Add VM Options.  Добавляем туда следующие значения (заменяя путь до вашего JavaFX SDK) --module-path {JAVAFX_SDK}\lib --add-modules javafx.controls Давайте попробуем запустить приложение и просто проверить, что оно работает. Если вы сделали все верно, то приложение запускается без особого труда. Теперь нам нужно переписать приложение таким образом чтобы сразу отобразилось окно загрузки и параллельно грузилось наше приложение. Для этого я нашёл GIF анимацию “загрузки” которую, я просто отображу, а затем уже нарисую весь остальной дизайн. Вы конечно можете сразу отрисовать дизайн, но это уже зависит от ваших задач. Мне рисовать ничего не надо, пока не поднимется база данных, по этому я отобразил загрузку приложения. У нас получился вот такой код, где в начале показывается окно загрузки, а затем приложение. Теперь, всё работает как надо у нас и можно писать дальше наше приложение с полноценным Spring Boot. Но что дальше, как распространять наше приложение?Что делать пользователям у которых нету JRE на компьютере?В целом уже давно есть множество решений данной проблемы, даже в составе JDK. В различных версиях Java начали появлятся различные тулы, такие, как JLink или JPackege. Эти инструменты позволяют вам создать приложение, которое можно будет запустить одним кликом. Но к сожалению у меня эти тулы так просто не завелись. По этому я предлагаю другое решение, а именно Launch4J. С его помощью можно будет создать EXE файл, который будет запускаться двойным кликом мышки. В целом там всё крайне просто. Собираем наше Spring приложение с помощью команды bootJar Скачиваем и устанавливаем Launch4J https://launch4j.sourceforge.net/  Запускаем его и настраиваем. Важны 3 основных поля (Output file, Jar, Icon) Идём в вкладку JRE и добавляем наши параметры для виртуальной машины(путь указываем именно такой, чуть позже станет понятно почему так) --module-path lib --add-modules javafx.controls  Готово, собираем нажав на шестеренку (он предложит сохранить файл конфигураций, сохраняем его) и готово. Мы получили наш Exe файл, но мы его не сможем запустить. Всё потому что у него нету библиотек для запуска JavaFX. Для этого вам нужно содержимое JavaFx SDK положить в туже папку, где и ваш EXE файл и распространять в месте с ним.  Наша программа запустилась. Теперь она работает независимо и красиво. Из рекомендаций могу дать совет запустить вашу программу и удалить всё, что можно из папок JavaFX SDK, Windows не даст удалить то, что используется, а всё лишнее удалится(но будьте осторожны, так можно удалить что то нужное, проверьте все внимательно). Таким образом я из 85 МБ сделал 11,5 МБ. Хотя конечно это не так критично, потому что само приложение со Spring boot и библиотеками весит 150 мегабайт, но уменьшил объем требуемых файлов на треть.  Ссылка на Github: https://github.com/kecven/JavaFX-with-Spring-Boot  Java Developer