Программы: Справочник географических объектов
08.04.2018


Введение

Сегодня будет много Джавы. Очень. Даже если это будет не совсем Java. Так что все хейтеры главного корпоративного языка и его платформы могут сразу закрывать вкладку браузера и идти собирать обновления для Gentoo.

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


Постановка задачи

Работа выполнялась по учёбе для двух разных предметов в разных, хоть и соседних, семестрах. Поэтому и задач будет две.

На первом предмете нам ставили целью научиться работать с разными базами и источниками данных. Одним из ключевых требований была загрузка данных либо из Microsoft Word, либо из Excel. В итоге должно получиться десктопное приложение.

На втором предмете упор делался на веб-технологии и создание серверных приложений на языке Java под контейнер сервлетов Tomcat. Поэтому нужно веб-приложение, работающее с базой данных.

Задача проста: составить справочних географических объектов и их адресов. Не знаю, как это нормально объяснить, поэтому предлагаю просто посмотреть пример заполненных данных в виде Excel'евской таблички (а именно с ней мы и будем работать).


Десктопное приложение

Главное окно приложения

Репозиторий

Пойдём в хронологическом порядке и начнём с обычной программы для персонального компьютера.

Как обычно, нам предлагали писать её на опенсорсном наследнике Delphi — Lazarus'е. Как вы понимаете, это ни разу не мой вариант. Ко времени выполнения работы я уже какое-то время писал небольшие части DeskChan на Джаве и успел немного освоиться в платформе JVM. Более того, местами уже даже начал вводиться Kotlin, изучению которого я посвятил пару тёплых летних недель. Поэтому не надо долго гадать, чтобы понять мой выбор.

К моменту начала разработки приложения уже был написан прототип DeskChan Launcher'а на Котлине. Причём мне очень понравилось: язык весьма приятен после многословной Джавы. Одним из сдерживающих факторов при разработке «Лончера» был размер выходного исполняемого файла: не хотелось, чтобы программу в 20-30 Мб ставил установщик в половину её размера. К сожалению, рантайм Котлина сам по себе привносит уже 800 Кб к размеру JARника, но дальше расти было крайне нежелательно. Поэтому отрисовка интерфейса там сделана с помощью JavaFX напрямую.

Однако для лабораторного проекта таких требований нет совершенно! Поэтому мы вольны использовать любые технологии и библиотеки! И первым же делом я добавил новую прослойку в построение формочек графического интерфейса — библиотеку TornadoFX. Приятный фреймворк для построения графических приложений на Котлине, который сразу призывает продумывать архитектуру и отделять слои приложения друг от друга. Главной же фишкой является описание экранных форм с помощью строго статически типизированных билдеров. Вряд ли такой способ полюбят дизайнеры, но если программисту приходится верстать UI, то такой подход — просто спасение.

Для работы с XLSX-файлами от Excel'я используем библиотеку Apache POI. Сразу скажу, что я дважды работал с этим форматом таблиц (в прошлый раз это было на С#'пе), и оба раза это была в той или иной степени, но боль. Старайтесь избегать таких извращённых форматов!

Вторым источником данных является реляционная база данных. Я пошёл по пути меньшего сопротивления и использовал уже установленную у меня MySQL, с которой можно спокойно работать по JDBC, установив соответствующий драйвер.

Весь код по работе с источниками данных находится в пакете ru.narfu.kozalo.addresses.data.sources. Там располагаются и все интерфейсы, и обе реализации.

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

Я пытался

На перепутье

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

И тут меня вновь понесло в сырые экспериментальные решения, коим стал проект kotlinx.html, позволяющий писать HTML-странички с помощью всё тех же типобезопасных билдеров. Сыроватость чувствуется в неуклюжем API, но задумка хорошая.

Жёстко обмазавшись DSLями (как чужими, так и самописным для задания роутинга), я запилил ряд страничек, которые позволяют просматривать (редактирование было лень делать) точно то же, что и в окне самого приложения.


Servlets serve you, sir

Репозиторий

Вот наконец мы и дошли до более энтерпрайзных и серьёзных технологий. Отныне никаких Котлинов и DSLей! Только читая Java! Причём седьмой версии! Сайтики мутить — это вам не формочки рисовать.

Тут необходимо краткое отступление о моём рабочем окружении. Вся сервлетная часть писалась исключительно на ноутбуке под управлением Debian 8. Из стандартных репозиториев был установлен Tomcat 8, который отказался работать с байт-кодом, скомпилированным под Java 8, поэтому пришлось откатиться до Java 7. Неприятно, но не очень страшно.

При работе с сервлетами сразу сталкиваемся с рядом проблем.

Во-первых, из коробки у меня ничего не заработало и Томкат не запускался. Пришлось читать логи и вручную править юниксовые права доступа.

Во-вторых, деплоить веб-приложение — это боль. Рекомендую сразу не полениться и прочитать главу про сервлеты у Шилдта. Сколько я не читал статей в интернете, а только у него нашлось нормальное введение, как на низком уровне работают сервлеты, без всяких надстроек вроде JSP. Тем не менее, вручную копировать классы, следуя его инструкциям, — удовольствие не из приятных. Поэтому я быстро научился загружать приложение WARкой через веб-интерфейс Томката, чем и довольствовался какое-то время, осваивая работу с сервлетами и контейнером.

На самом деле в IDE есть средства для автоматизации загрузки приложений в контейнер сервлетов, но у меня так и не получилось настроить это по-человечески. IntelliJ IDEA самостоятельно запускает и отключает Томкат, из-за чего требует прав администратора. Я не понимаю, зачем это нужно, если можно просто редеплоить новые WARки.

И тут на помощь приходит Maven со своими бесконечными плагинами! Только поставив tomcat7-maven-plugin (он подходит и для 8-го Томката) я смог вздохнуть спокойно и начать жить счастливо. Не поленитесь его установить! Он позволяет (ре)деплоить приложение в один клик, используя всё тот же RESTful API, что и сайт самого Томката.

Ладно, перейдём ближе к коду. Разобравшись, как это всё работает, и вооружившись дополнительной библиотекой тегов, я смог быстренько на JSP накидать странички с отображением адресов, повторив функционал серверной части десктопного приложения. Но поскольку в задании было требование и на возможность редактирования записей, пришлось доделать дополнительные формочки и сделать простенький REST API на чистых, вручную написанных сервлетах (JSP компилируются в классы при первом обращении).

Кстати! В этот рад для общения с СУБД я решил опробовать знаменитый Hibernate, оформив все сущности по спецификации JPA (в Java EE'шных стандартах очень много аббревиатур). В принципе получилось неплохо, но где-то я всё-таки налажал, потому что временами происходит блокировка БД, которая чинится перезапуском контейнера сервлетов. У меня уже не было сил искать причину такой серьёзной поломки, так что если кто-нибудь ткнёт меня носом на косяк в комментариях, то я буду очень благодарен.


Заключение

В целом, если подводить какой-то итог, экселевские таблицы — это зло, энтерпрайзные технологии — чуть меньшее, но тоже зло. Kotlin няшен, но не для всех технологий применим (ах да, я же забыл упомянуть, почему не стал писать на нём сайт! Мне было лень думать, как лучше всего подружить изменяемые джавовские объекты, используемые Hibernate'ом, со всем таким неизменяемым Котлином) и ещё сыроват в плане инфраструктуры. Надеюсь, дальше будет лучше: с платформой JVM я бы ещё поработал. В конце концов под неё есть ещё много более функциональных языков, с которыми мне хотелось бы ознакомиться…


Дополнено 3 июня 2018 года

На самом деле я жутко протупил с этим дополнением, потому что его надо было добавить ещё 9 апреля. Но сначала было лень, потом некогда и так всё закрутилось… В общем мне сказали, что всё фигня и ничего из описанного в части про серверную Джаву не нужно использовать, если ты не наркоман.

Мудрости от @DogeShibu