Привет! Я Виктор Барсуков, Java-разработчик в Lamoda. В этой статье я хочу рассказать о разработке десктопного Java-приложения, что из этого получилось и что можно было бы сделать иначе.

В 2019 году в России ввели обязательную маркировку ряда товаров. В связи с этим малому бизнесу пришлось покупать и настраивать дорогие по меркам МСП (то есть, малых и средних предпринимателей) программы и оборудование. 

У меня есть такие знакомые, и из общения с ними я знаю, что в России малому бизнесу и без маркировки хватает забот. Поэтому решил внести посильный вклад в развитие МСП. Но какой вклад может сделать программист? Написать программу. Программу с одной-единственной функцией — печатью кодов маркировки, которая должна помочь соблюсти требования новых законов и избежать непомерных штрафов.

Предыстория проекта

С 2019 года в РФ введена обязательная маркировка ряда товаров. Более подробно об этом можно узнать на сайте Честного Знака. На момент старта маркировки было много нерешенных вопросов, которые озвучивались в профильных чатах. Малым предприятиям требовалось приобретать и настраивать достаточно дорогие программные решения. В результате многие покупали 1С со всем его богатым набором функций исключительно ради печати DataMatrix-кодов.

Мне показалось, что ситуацию вполне можно исправить, написав программу с единственной функцией — печать кодов маркировки. Собственно, с этого все и началось.

Дисклеймер: сразу оговорюсь, что проект делается в свободное от основной работы время, поэтому глубоко исследовать разные технологии было некогда. Часто приходилось выбирать не самое оптимальное решение, а первое, которое показалось приемлемым, и с хорошо описанной документацией.

Используемые технологии

Так как я Java-разработчик, то неудивительно, что в первую очередь рассматривался знакомый язык. Конечно, Java чаще всего ассоциируется с разработкой бэкенда, но я решил попробовать его для десктопа.

При разработке десктопного приложения на Java выбор в принципе стоит между JavaFx и Swing. JavaFx показался дружелюбным в разработке, поэтому выбор пал на него. Swing все-таки считается устаревшей технологией и даже Oracle говорит о замене Swing на JavaFx.

Изначально проект был на Java 8, потому что у него еще есть поддержка JavaFx. В более старших версиях эту функцию убрали, поэтому потребуются определенные танцы с бубном для запуска приложения. Ниже опишу, как удалось обойтись без них и продолжить поддерживать актуальный стек. 

Сборка дистрибутива

Первые версии приложения поставлялись как fat-jar со всеми зависимостями, но это оказалось неудобно. Целевая аудитория — малые предприниматели, у которых уровень владения компьютером чаще всего на уровне пользователя, изредка — продвинутого пользователя. Для них оказалось весьма проблематично устанавливать Java правильной версии, а потом запускать приложение через bat-файл. 

Сначала я рекомендовал сборку Java от Liberica: после инсталляции она связывает зависимости, и приложение запускается просто по двойному клику мыши. Но даже после этого при вводе запроса «barCodesFX» Google продолжал автоматом подсказывать «как запустить». К счастью, сейчас ситуация поменялась.

Эта подсказка натолкнула меня на мысль, что приложение должно запускаться через exe-файл по двойному клику без установки дополнительного ПО. Или же это ПО должно ставиться автоматом.

В поисках решения нашелся проект Launch4j. Он позволяет создавать exe-файл, выступающий в роли «стартера» для основного jar-приложения. При этом JRE «правильной» версии помещается в состав дистрибутива и не требует отдельной установки. Это увеличило размер дистрибутива, но в век безлимитного интернета лишние 70 Мб для удобства пользователя не кажутся критичными.

Отдельная благодарность команде Liberica, которая поставляет сборки JRE с подключенными модулями JavaFx — это сильно облегчает запуск приложения.

Сам exe-файл создается при сборке после добавления плагина в maven-проект.

<plugin>
   <groupId>com.akathist.maven.plugins.launch4j</groupId>
   <artifactId>launch4j-maven-plugin</artifactId>
   <version>2.1.2</version>
   <executions>
       <execution>
           <id>l4j-clui</id>
           <phase>compile</phase>
           <goals><goal>launch4j</goal></goals>
           <configuration>
               <headerType>gui</headerType>
               <outfile>target/BarCodesFX.exe</outfile>
               <jar>barCodesFX.jar</jar>
               <icon>src/main/resources/microQR.ico</icon>
               <downloadUrl>https://download.oracle.com/java/17/archive/jdk-17.0.1_windows-x64_bin.msi</downloadUrl>
               <errTitle>Launching error</errTitle>
               <dontWrapJar>true</dontWrapJar>
               <jre>
                   <path>%PWD%/jre-17.0.1</path>
                   <jdkPreference>preferJdk</jdkPreference>
                   <initialHeapPercent>20</initialHeapPercent>
                   <maxHeapPercent>80</maxHeapPercent>
               </jre>
               <versionInfo>
                   <fileVersion>0.0.0.0</fileVersion>
                   <txtFileVersion>${version}</txtFileVersion>
                   <fileDescription>BarCodesFX-${version}</fileDescription>
                   <copyright>Barsukov Viktor</copyright>
                   <productVersion>0.0.0.0</productVersion>
                   <txtProductVersion>${version}</txtProductVersion>
                   <productName>BarCodesFX</productName>
                   <internalName>BarCodesFX</internalName>
                   <originalFilename>BarCodesFX.exe</originalFilename>
               </versionInfo>
               <messages>
                   <startupErr>Startup error</startupErr>
                   <bundledJreErr>Bundled Jre Error</bundledJreErr>
                   <jreVersionErr>Jre Version Error</jreVersionErr>
                   <launcherErr>Launcher Error</launcherErr>
               </messages>
           </configuration>
       </execution>
   </executions>
</plugin>

Через несколько недель после компоновки дистрибутива был обнаружен задокументированный баг: если в пути к exe-файлу есть названия папок на национальных языках (то есть на любом, кроме английского), то приложение не запускается. К счастью, проект Launch4j в целом живой и этот баг пофиксили.

Далее zip-архив вручную упаковывается в SFX-архив и выкладывается в SourceForge. Теперь пользователь может спокойно скачать единственный установочный exe-файл, несколько раз нажать ОК и Далее и получить работающую программу. 

Функциональность расширяется: подключаю Spring и СУБД

Проект развивался по классическому Agile: вначале скейт, потом самокат, потом велосипед. На старте основная функциональность заключалась в печати датаматриксов. Потом добавилось генерирование XML-файлов, а в самой программе появились настройки. 

Изначально настройки хранились в файле и подтягивались с запуском приложения, однако для пользователей это было неудобно и неочевидно. Затем все переехало в графический интерфейс, но тут начались проблемы с общим доступом к файлу настроек и стало понятно, что не хватает базы данных. Для создания БД мне захотелось использовать знакомый фреймворк, а не писать все с нуля, поэтому я подключил к проекту Spring.

К счастью, есть проект JavaFX Weaver, который решает проблемы получения колючей проволоки путем скрещивания ежа и ужа: контроллеры превращаются в бины, dependency injection становятся доступными и становятся доступными прочие плюшки Spring. Но главное — не требуется полностью переписывать все приложение.

В качестве базы данных была выбрана H2. Она легковесная и не требует установки. Пользователь просто запускает приложение и все работает без предварительной установки СУБД.

Добавление шаблонизатора

Проект изначально был опенсорсный, поэтому довольно быстро набрал популярность. Но конкуренты не дремлют: для увеличения трафика коммерческие компании создавали свои бесплатные решения. И у этих решений было одно ключевое преимущество —  возможность создавать в удобном графическом редакторе свой шаблон этикетки.

Для меня разработка такой функциональности была непозволительной роскошью, потому что заняла бы много времени без гарантии положительного результата. Однако мне все же хотелось добавить шаблонизатор. По умолчанию в моем приложении было только два варианта печати: либо А4, либо термопринтер. На самой этикетке выводился только датаматрикс и чуть-чуть пользовательского текста.

Первый вариант наклеек для листа А4, а второй — для термопринтера
Первый вариант наклеек для листа А4, а второй — для термопринтера

В поисках решения я подробно изучил продукты компании iText. Их библиотека iТext PDF используется в BarCodesFX для генерации PDF. У нее есть много разных функций и при этом она полностью бесплатная при использовании в опенсорс-проектах. В коде можно полностью собрать pdf-файл с форматированием, дополнительными элементами и картинками. Через нее же происходит преобразование строки в датаматрикс.

У них же обнаружил pdfHTML — библиотеку, которая преобразует HTML-страницу в PDF. Внутри нее нашлась функциональность для заполнения HTML-шаблона. Так у пользователя появилась возможность самостоятельно сверстать практически любую этикетку, а не ограничиваться предустановленными шаблонами.

В шаблоне часть тегов нужно было заменять на пользовательские значения. Например, вместо <datamatrix/> выводить картинку кода, а вместо <page_number/> — номер страницы. Для этого разработчику достаточно в свойствах передать свою CustomTagWorkerFactory, которая наследует от DefaultTagWorkerFactory. Таким образом, все изменения гармонично встраиваются в поток обработки HTML-кода, при необходимости заменяя дефолтные обработчики тегов на собственные, с помощью имплементации интерфейса ITagWorker . 

properties.setTagWorkerFactory(new CustomTagWorkerFactory());
List<IElement> elements =
   HtmlConverter.convertToElements(new FileInputStream(htmlSource), properties);

for (IElement element : elements) {
   document.add((IBlockElement) element);
}

Можно сказать, что в целом шаблонизатор удался и им активно пользуются. Из 194 млн распечатанных кодов 25 млн было сгенерированно с использованием шаблонизатора. В качестве источника данных для заполнения полей типа артикула, цвета и размера используется эксель-файл.

Итоговая кастомизированная наклейка
Итоговая кастомизированная наклейка

Хотя не обошлось и без нюансов при верстке. Например, если ваш кастомный тег <datamatrix/> обернуть в <div>, то замена не произойдет. Такая вот особенность библиотеки.

Попытки интеграций с API

За время существования проекта было две попытки интеграций с API операторов маркировки.

Первая интеграция была с СУЗ (станцией управления заказами) оператора ЦРПТ (Центра развития перспективных технологий). Она прошла успешно, все работало, но в какой-то момент оператор без предупреждения изменил поведение API. Это привело к массовым обращениям от пользователей, которые сообщали об ошибках в работе приложения.

Так как я занимаюсь проектом в свободное время, то не могу быстро реагировать на такие изменения и обеспечить требуемый уровень поддержки. Поэтому от интеграции с API пришлось отказаться. Кроме того, добавилась необходимость использовать КриптоПро для авторизации, так что эта задача задвинулась в дальний угол. 

Вообще работа с криптографией — это весьма интересная задача. Но использовать отечественного криптопровайдера типа КриптоПро в десктопном Java-приложении — это задача «со звездочкой».

Вторая попытка интеграции была с API оператора Республики Беларусь. Авторизация у оператора проходила по логину и паролю и не требовала наличия крипто-провайдера. Функциональность была готова к релизу, но в последний момент пришлось отказаться.

  • Во-первых, была плохая коммуникация с поддержкой оператора РБ, нежелание разбираться и что-то решать. Их позиция: «У нас все работает, проблема на вашей стороне».

  • Во-вторых, нарушение стандарта RFC 8259 при реализации API. В чате поддержка оператора сказала, что символы GS не нужно экранировать при использовании их API. Это дважды нарушает 7-ой пункт стандарта.

Вместе два этих фактора давали гремучую смесь. Пользователи пытались бы использовать внедренную функциональность, а она не работает должным образом. Обращения шли бы ко мне, отнимая много времени на разбор ошибок. Только после подробного разбора стоило идти к оператору. При этом высока вероятность, что оператор просто «отфутболит» мой запрос, потому что я даже не являюсь резидентом. А с точки зрения пользователя — проблема в программе.

Генерация XML

Чтобы при работе на сайте не отмечать каждый код в длинном списке, Честный Знак добавил возможность загружать коды файлами. Например, вам нужно списать 2000 кодов и вы просто загружаете один файл, а не выискиваете все эти коды и не прокликиваете их по одному. 

Однако файл должен быть в xml-формате с правильно заполненными тегами. Вручную его создавать еще сложнее, чем прокликивать коды по одному. И именно с созданием таких файлов и помогает программа.

Задача создания xml-файлов достаточно типовая, поэтому здесь особо нечего рассказывать, кроме трех интересных моментов:

Для генерации XML используется библиотека Jackson FasterXML. При сериализации списков пришлось добавить кастомный StdSerializer, иначе вместо этого…

<products_list>
    <product>
      <ki>0104600840362250215&lt;QCkpilDMTLs</ki>
    </product>
    <product>
      <ki>0104600840362250215*uJEIn4EH&gt;Rd</ki>
    </product>
</products_list>

… получали лишние теги product вокруг списка.

<products_list>
<product>
    <product>
        <ki>0104600840362250215&lt;QCkpilDMTLs</ki>
    </product>
    <product>
        <ki>0104600840362250215*uJEIn4EH&gt;Rd</ki>
    </product>
</product>
</products_list>

Разрулить ситуацию через аннотации не представлялось возможным, потому что классы генерируются автоматически на базе XSD-схем. 

ЦРПТ ввели дополнительные правила экранирования символов в кодах маркировки в XML. По этой причине нужно было экранировать одинарные и двойные кавычки, хотя этого не требуется по стандарту (пункт 2.4). 

К счастью, в библиотеке FasterXML это удалось решить добавлением кастомной EscapingWriterFactory.

public Writer createEscapingWriterFor(final Writer out, String enc) {

   return new Writer(){
       @Override
       public void write(char[] cbuf, int off, int len) throws IOException {

           String val = "";
           for (int i = off; i < len; i++) {
               val += cbuf[i];
           }
           String escapedStr =  StringEscapeUtils.escapeXml(val);
           out.write(escapedStr);
       }

       @Override
       public void flush() throws IOException {
           out.flush();
       }

       @Override
       public void close() throws IOException {
           out.close();
       }
   };
}

ЦРПТ предоставляет некорректные xsd-схемы. Схемы разделены по документам: есть документ на ввод в оборот, вывод из оборота, списание. Для каждого документа есть свой xsd-файл и при этом есть общая для всех схема — «Определенные пользовательские типы». 

Общая схема добавляется через импорт в схемы документов. Например, в схеме документа списания есть такой элемент:

 <xs:element name="cis" type="cis_type">
   <xs:annotation>
     <xs:documentation>Код идентификации</xs:documentation>
   </xs:annotation>

Однако тип cis_type не отражен в общей схеме «Определенные пользовательские типы». Такие типы приходилось допридумывать самостоятельно, потому что даже техподдержка не смогла предоставить полностью валидные схемы.

Тесты

Боль. Их просто нет. А для уважающего себя проекта они должны быть написаны — хотя бы юнит-тесты. Но на все не хватает времени.

И к сожалению, нет ни малейшего представления, как можно тестировать сам интерфейс. Вся надежда на проект TestFX, но пока у меня еще не дошли руки посмотреть его подробнее.

Что стоило бы изначально сделать иначе

Контроллер. Сейчас при запуске приложения открывается форма со множеством вкладок, которые программно управляются из одного класса-контроллера. Из-за этого класс достигает размера под 1000 строк. Можно было бы подключать каждую вкладку как отдельный FXML-файл со своим контроллером — это сделало бы программу намного удобней в разработке и поддержке.

Подключить DI (dependency injection) на более ранних этапах. Это повлияло бы в целом на архитектуру и упростило как разработку, так и дальнейшую поддержку. До сих пор в коде видны следы разработки до DI с ручным управлением жизненным циклом объекта. Изначально при написании пришлось потратить время на кодирование жизненного цикла и при дальнейшей разработке приходится помнить об этой особенности.

Немного статистики

Поделюсь статистикой скачиваний за все время существования проекта. Пик в 7000 скачиваний — это выброс из-за сбоя в SourceForge, когда вместо загрузки файла заново запускался таймер, и так до бесконечности. При этом прокручивался счётчик скачиваний. Остальные пики совпадают с этапами внедрения маркировки.

Пик скачивания из РБ (Республика Беларусь) в последние месяцы обусловлен тем, что программа была официально рекомендована оператором РБ для формирования pdf файлов с этикетками.

Согласно статистике самой программы за все время существования проекта с ее помощью распечатали приблизительно 184 000 000 этикеток и ввели в оборот около 210 000 000 единиц товара, а отгрузили почти 81 000 000 единиц товаров.

Статистика собирается обезличенно, о чем указано в описании к программе. При желании сбор статистики можно отключить. Дружественная компания предоставила серверные мощности для сбора данных.

Цифры приблизительные, потому что статистику начали собирать уже после старта обязательной маркировки обуви. Кроме того, сгенерировать PDF — не значит его распечатать. К тому же у ряда пользователей программа находится за корпоративным фаерволом, поэтому статистика просто не доходит до сервера.

Выводы

Разрабатывать десктопные приложения на JavaFx можно: технология живая и достаточно удобная за счет разделения view и controller. В графическом редакторе можно набросать FXML-форму, потом прописать ей поведение в контроллере. Есть подключаемые библиотеки с дополнительными элементами форм. А еще можно написать свои элементы при необходимости. Есть возможность задействовать сторонние фреймворки типа Spring — он работает с современными версиями Java.

Подводя итог можно сказать следующее: если вы Java-разработчик и перед вами поставлена задача сделать утилитное десктопное приложение для внутреннего использования, то JavaFx — хороший выбор. Для написания небольших прикладных программ его более, чем достаточно.

Если же вам нужно сделать коммерческое решение с красивой визуальной картинкой, использующее особенности конкретной ОС (например, сворачивание в трей или показ всплывающих уведомлений), то скорее всего вам потребуется другое решение.

Спасибо, что дочитали, буду рад ответить на вопросы в комментариях.

Ссылка на проект, ссылка на исходники

Комментарии (46)


  1. grishkaa
    02.02.2022 12:01

    Всё хочу когда-нибудь попробовать написать приложение для macOS на джаве с помощью rococoa. Кроссплатформенные графические интерфейсы всегда выглядят и ведут себя как что-то чужеродное.


    1. nick_rom0
      02.02.2022 17:27
      +3

      Думаю нужно просто делать целостную визуальную концепцию приложения, как Photoshop или IDEA


    1. IvaYan
      02.02.2022 20:08

      Есть ещё VAqua -- свингвский LaF с закосом под Мак.


  1. CrushBy
    02.02.2022 12:34
    +1

    А почему в качестве шаблонизатора и собственно печати PDF (а можно и напрямую на принтер, плюс в другие форматы) не использовали JasperReports под LGPL ? Там можно визуально рисовать шаблон (он, кстати, для экспорта в PDF и использует iText, насколько я помню).


    1. victor_2004 Автор
      02.02.2022 21:57

      С JasperReports у меня опыта работы не было. В голове почему-то отложилось, что это жутко сложная и жутко платная штука энтерпрайз уровня, требующая установки серверной части. Поэтому ее даже не стал смотреть.

      ЦРПТ по умолчанию работает с шаблонам в формате JasperReports. И судя по обсуждениям мало у кого из пользователей получилось их самостоятельно обновить/доработать без приключений.


      1. CrushBy
        03.02.2022 09:07
        +1

        Много лет работаем с JasperReports и особо крупных проблем не возникало (хотя возможно когда-то давно их решили и забыли).

        жутко платная штука энтерпрайз уровня, требующая установки серверной части

        Это вы скорее всего говорите про JasperReports Server (и он под AGPL). Речь шла про JasperReports Library. А именно для визуального редактирования шаблонов ставится JasperSoft Studio под лицензией Eclipse. Единственно, конечно, что в Jasper'е плохо, что они начали еще делать редактор под Eclipse, а не под IDEA (которой мы пользуемся). Так бы было вообще замечательно.


        1. victor_2004 Автор
          03.02.2022 11:43
          +1

          Спасибо за комментарий, в будущем буду иметь ввиду.


  1. Breathe_the_pressure
    02.02.2022 12:35
    +4

    А .NET почему не выбрали? Это же всё на Винде живёт?


    1. Phrynohyas
      02.02.2022 13:31
      +8

      Потому что для человека родной стек - Java.
      ЗЫ Сейчас .NET отлично живет и на Линуксе с Макосью. Авалония, UNO, новомодный MAUI (тут пока без Линукса, к сожалению) вполне позволяют создавать кроссплатформенные интерфейсы.


      1. Breathe_the_pressure
        02.02.2022 15:24
        -9

        Читать то я умею, хотелось бы от автора услышать. А вы я так понимаю, пресс секретарь?


      1. victor_2004 Автор
        02.02.2022 22:03
        +4

        Абсолютно так. Родной стек. При этом .NET в моем случае не дополняет его, а конкурирует с ним. В отличии, например, от того же JavaScript.

        Поэтому не вижу смысла изучать еще один инструмент с похожим функционалом без острой необходимости.


  1. j_wayne
    02.02.2022 12:59
    +1

    Есть стоковый packager, который производит нативные запускаторы.
    Вроде бы это:
    https://docs.oracle.com/javafx/2/deployment/self-contained-packaging.htm
    Давно это было, деталей не помню, помню, что даже maven plugin был и все автоматом собиралось, единственное неудобство - нужно собирать на целевой платформе, кроссбилдинга нет. Но это понятно, там еще и jre эмбеддится.


    1. victor_2004 Автор
      02.02.2022 22:11

      Этот вариант я тоже в свое время рассматривал, но упоминание NetBeans убавило энтузиазм :-)

      Плюс - с launch4j я и ранее работал, в целом знаком с библиотекой. И она более универсальна, без привязки к JavaFx. В принципе в нее можно завернуть любой jar-ник.

      Если и переходить на новые механизмы, то уж лучше сразу jpackage пробовать. (https://docs.oracle.com/en/java/javase/14/docs/specs/man/jpackage.html)


      1. j_wayne
        03.02.2022 10:47

        Кстати нет, NetBeans использовать не пришлось - видимо просто для примера там упомянули. Работает действительно только с GUI приложениями.


  1. MentalBlood
    02.02.2022 13:17
    +1

    А для уважающего себя проекта они должны быть написаны — хотя бы юнит-тесты

    Для щадящего себя разработчика скорее ) Потому что иначе либо тестить ручками и тратить адову тучу времени, либо обнаруживать баги внезапно и никогда не знать наверняка вылезли ли они снова после очередных изменений


  1. Hayter
    02.02.2022 13:31
    +1

    А почему именно десктоп, а не веб сервис?


    1. victor_2004 Автор
      02.02.2022 22:37
      +5

      В первую очередь мощности. Они стоят денег. Плюс - единая точка отказа. В пиковые моменты внедрения маркировки вебсервисы по генерации кодов просто ложились. А так пользователь ограничен исключительно своими собственными вычислительными мощностями.

      И не зависим от наличия интернета.


      1. vsh797
        03.02.2022 11:06

        Чтоб не было нагрузок можно было frontend приложение сделать. Хотя, конечно, его б не на java пришлось писать. Как минимум вопрос с распространением приложения был бы проще. Не знаю, правда, есть ли для js все нужные библиотеки..


        1. victor_2004 Автор
          05.02.2022 00:56

          Если ты делаешь веб приложение, то ты несешь больше ответственности перед пользователями. Тебе нельзя просто сказать "я устал, денег на сервера больше нет, выключаемся". Люди завязывются на твое решение и это будет не честно по отношению к ним. Так же нужно следить за хостингами, доступностями, SSL сертификатами и пр. В случае с десктопом - можно просто забросить проект и старый функционал будет стабильно работать.

          Аналогично с релизами. В случае с десктопом цена ошибки ниже. Если выявляется критическая бага, то пользователь просто будет пользоваться предыдущей версией. В одной из версий окно сканирования просто перестало открываться (не отследил при проверке). Пользователи просто рапортовали баг и продолжили пользоваться предыдущей версией. В случае с вебом мне пришлось бы все бросать, откатываться или срочно чинить.

          Ну и по правде говоря - с интернетом у нас далеко не везде хорошо. Те же молочные фермы часто стоят в поле без связи. Им раз в неделю привозят флешку с файлами, они с ней и работают.


          1. vsh797
            05.02.2022 09:18

            Так же нужно следить за хостингами, доступностями, SSL сертификатами и пр.

            Github pages очень удобен в этом плане.


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

            В вебе релиз полностью под твоим контролем. Мне наоборот казалось, что это преимущество. Нашел багу — обновил сразу для всех. Нужно откатиться — для stateless сервиса это очень легко делается.


            Но вообще ваше решение хорошо понятно и имеет безусловные плюсы. Особенно в контексте работы по флешке.


  1. SnowBearRu
    02.02.2022 14:38

    Да там не много пляски на 11 яве + отдельно fx поставить, за пару часов бы управились.

    Тогда бы можно было уже попробовать и плюшки явы 8++ ,например Jigsaw


  1. amarkevich
    02.02.2022 15:58

    В своё время для ГУИ использовал SWT

    Лаунчером был простой скрипт

    start jre\bin\javaw -jar app.jar

    jre добавлялось вручную. но это было до появления Packaging Tool


  1. Throwable
    02.02.2022 20:17
    +1

    Наверное единственный оставшийся серьезный юзер у свинга -- это Jetbrains :) Он же по совместительству и основной контрибьютор.

    Вообще нынче модно делать локальные веб приложения и паковать их в электрон. Если нужна обязательно Java, взять какой-нибудь Vaadin или Kotlin Multiplatform...


    1. slavap
      03.02.2022 06:05

      GWT рулит


    1. Garifullin_Ilmar
      04.02.2022 17:49

      Я не автор , но Ваадин мне кажется довольно тяжеловесным для простого десктопного приложения


  1. maxzh83
    02.02.2022 20:28
    +1

    Вижу у проекта есть возможность доната. Если не секрет, народ донатит? Можно не сумму, а какую-то свою свою оценку. Просто часто вижу, что народ неохотно донатит на софт, даже когда он экономит им прилично денег.


    1. victor_2004 Автор
      02.02.2022 23:17
      +6

      Активно донатили на старте маркировки в 2020 г. Когда нужно было промаркировать остатки и коды печатались миллионами. Средний размер доната 300 - 500 р., 3-5 доната в месяц. Когда-то побольше, когда-то поменьше. Иногда приходили с запросами "мы вот хотим пару тысяч задонатить и нам вот такого вот функционала ну очень не хватает". Но это единичные случаи.

      Сейчас уже в целом ситуация утряслась, донатов практически нет.

      При этом при старте маркировки в Беларуси в конце 2021 года программа была рекомендована Электронным Знаком (аналог ЦРПТ в РБ) для печати кодов (они со мной предварительно связывались, согласовывали этот вопрос).

      Скачиваний в РБ было порядка 5000. А вот донатов практически нет :-). Видимо воспринимается людьми как предоставляемое оператором.


      1. maxzh83
        03.02.2022 15:06

        Спасибо за информацию, примерно так и думал.


        1. kAIST
          04.02.2022 12:20

          Да вроде это не новость что донаты в этой сфере не работают. Даже у крупных проектов основное финансирование идёт не от донатов рядовых пользователей.


    1. victor_2004 Автор
      02.02.2022 23:20
      +5

      Ну собственно я и не рассчитывал с донатов много заработать, это просто возможность для людей высказать благодарность в финансовом эквиваленте. Заодно с тех денег даже лицензию WinRar приобрел. Раз уж я его так активно использую для формирования SFX архивов.

      Причем один раз даже просто позвонили, чтобы сказать спасибо. Было очень приятно :-)


  1. erzi
    02.02.2022 23:51

    Непонятно

    "Swing ... считается устаревшей технологией... Изначально проект был на Java 8, потому что у него еще есть поддержка JavaFx. В более старших версиях эту функцию убрали, поэтому потребуются определенные танцы с бубном для запуска приложения"

    Тогда надо было делать на Swing без бубнов и на всех системах бы работало 


  1. sved
    03.02.2022 00:09
    +2

    Интересно на чём нонче вообще дестктопные приложения пишутся, так чтобы модно, правильно и современно?

    WinAPI, Windows Forms? Вроде устарело. Электрон - тормоз. Свинг не развивается.

    QT - косяки и язык так себе.

    Такое впечатление, что десктоп разработка застыла где-то в прошлом веке


    1. Sigest
      03.02.2022 07:51

      Да электрон вроде исправляется. Года два назад было ужасно, но сейчас, кажется, более или менее стабильно, я даже я не замечаю, что приложение на электрон: Postman, Slack, Lens работают норм. Или это действительно не электрон приложения


    1. timofeevka
      03.02.2022 09:39
      +1

      Ну хз у кого на чем, а у меня для windows - Delphi VCL и с того же кода для Linux - FPC+Lazarus для GTK2. Альтернатив не сильно много: QT, Java FX, Flutter больше для мобилок, Delphi/Lazarus как ни странно. А вообще выскажу такую мысль, что возможно в нынешнее время в качестве десктопного GUI имело бы смысл затачивать игровые движки, ну типа Unity.


  1. PocketM
    03.02.2022 01:00
    +2

    Сейчас еще есть graalvm.org, умеет делать нативные бинарники (в т.ч exe для win) без необходимости тащить с собой JVM.


    1. victor_2004 Автор
      03.02.2022 11:47
      +2

      На хабре есть статья от Отуса как они спринг бутовое приложение упаковывали в exe. Мне показалось, что в целом концепт интересен, но еще в экспериментальной стадии. Думаю к этому вопросу можно будет вернуться через год и посмореть какие были подвижки.


  1. oldd
    03.02.2022 10:03
    +4

    Как работающий на JavaFx более 5 лет, сильно рекомендую запаковать все требуемые библиотеки javafx прям в jar. Этим вы упростите себе жизнь, т.к. недокументированные особенности и баги меняются от версии к версии и то, что на вашей либерике работает нормально, на следующей либерике может поломаться.


    1. victor_2004 Автор
      05.02.2022 00:47

      Буду иметь ввиду, спасибо за совет.


  1. morincer
    04.02.2022 11:38
    +1

    Тоже в январские каникулы начал писать свой десктопный пет-проект на Java 9 - JavaFX вполне себе живее всех живых, использовал в связке с MvvmFx. Написал бОльшую часть функционала, но когда дошла речь до упаковки - просто ступор.

    Сначала решил пойти путём "by design" и использовать jlink, надеясь на выходе получить красивый дистрибутив с кастомной JRE - в конце концов, именно для этого он и был придуман. Возможно, я неправильно их готовил, но, по моему опыту, модули из Java 9+ - это тихий ужас, когда в проекте много сторонних библиотек. Самый главный вопрос, который меня мучал - сколько еще, блин, раз я должен описывать свои зависимости? В pom.xml укажи, в module-info укажи, в аргументах jlink укажи. Что характерно, дистрибутив так и не собрался - где-то там в глубинах окопался автоматический модуль, работать с которым jlink отказался. Короче, бросил я этот кактус, и стал смотреть в сторону fatjar (господи, fatjar в 2022 году, классика не устаревает). Честно говоря, результаты меня тоже не очень удовлетворили - как по размеру, так и по процессу сборки.

    Посмотрел я на свою коровенку и понял, что она в текущем виде предназначена для работы исключительно под Windows (там используются голосовые функции, которые, к сожалению, после долгого мучения с MaryTTS и CMUSphynx, пришлось реализовать в виде работы с Windows Speech API через прокси), поддержки ни Linux, ни мобильных OS не требуется (в виду специфики продукта).

    И перетащил все на C# + WPF, благо бОльшая часть логики и тестов переносятся практически буквально (языковые конструкции отличаются в основном синтаксисом, stream API -> Linq, naming conventions поправляются IDE). Процесс перевода core занял один вечер, собственно, основное время заняло переписывание UI - давно я с WPF не работал, но в целом, процесс тоже не сложный. IDE - пересел с Jetbrains IDEA на Jetbrains Rider, в целом безболезненно.

    Пока не жалею. WPF по функционалу - гораздо гибче JavaFX, хотя, конечно, не без нюансов. Практически все аналоги нужных библиотек имеются. Работа с Windows Speech - из коробки. Exe на выходе - из коробки.


    1. victor_2004 Автор
      05.02.2022 00:42

      А почему брали девятую джаву? Мне кажется правильнее использовать LTS версии. 8,11,17.

      Лично мне удалось добиться, что дистрибутив собирается сам в архивчик со всеми необходимыми зависимостями по стандартному clean install. Но вот размер да, печалит. Хотя при нынешнем широкополосном интернете лишние 75 мб мне не кажутся критичными. Но если java начнут поставлять в составе стандартной собрки винды, как это сейчас происходит с .NET, то и необходимость добавлять jre в состав дистрибутива пропадет.


      1. morincer
        05.02.2022 11:16

        А почему брали девятую джаву

        В комменте ошибся, сейчас посмотрел - 11-я. Но посыл был в том, что "уже не восьмая" :)


  1. djamali
    04.02.2022 17:49

    Круто. А как вы решили задачу сериализации корутинных процессов на компилируемых хешах лямбда выражений?


    1. victor_2004 Автор
      05.02.2022 00:43

      Такого рода задачи программой не решаются.


  1. froloi
    04.02.2022 17:51

    А как вы при печати qr формируете крипто-хвост?


    1. victor_2004 Автор
      05.02.2022 00:46

      Никак. Он должен быть передан программе в текстовом файле для печати. Если в файле передаются урезанные коды(без крипто части), то программа выдаст предупреждение о невалидности кодов.

      В настройках заложена опция отключения этой проверки. Возможно я был не прав, что сделал ее. Часть пользователей не разобравшись что же не так с их кодами просто отключали проверку. В результате их ждет увлекательнейшее приключение с вылавливанием битых кодов, перемаркировкой уже на складах, кассах.


  1. RuJet
    05.02.2022 09:39

    Спасибо автору за классное ПО.

    Я один из той армии пользователей, которые печатали марки для остатков из BarcodeFX.

    Донат тоже был.