[Программирование, Java, Amazon Web Services, Gradle, Облачные сервисы] Если у вас не работает Spring BootJar

Автор Сообщение
news_bot ®

Стаж: 6 лет 4 месяца
Сообщений: 27286

Создавать темы news_bot ® написал(а)
28-Дек-2020 02:31

Проблема с загрузкой Spring Boot Jar

Сталкивались ли вы с проблемой запуска нового загрузочного архива Spring Boot?
Вообще, новация в этом направлении уже не первая, стандартов особых нет. Поэтому многие огребают проблемы и решают их на форумах и стек-оверфлоу.
Если вы также столкнулись с проблемой, я помогу её решить. В таком случае читаем дальше.
Итак, проблем с BootJar на самом деле хватает. Особенно учитывая, что уже минимум три версии формата поменялось.
Здесь я расскажу о часто встречающемся случае с потерей ресурсов. Конкретнее в моём случае — с потерей JSP шаблонов. Почему JSP? Мне так привычнее, проект я по-быстрому начал с них, и не думал, что будут такие проблемы.
Итак структура проекта (стандартный веб):
/src/main/
    java/
    resources/
        static/
            some.html
        public/
    webapp/
        WEB-INF/jsp
            index.jsp

По заявлению создателей BootJar / BootWar, jsp не поддерживается толком в новом BootJar формате. Но совместимость должна быть в BootWar. На это я и надеялся, когда ваял код. Пока ваял, никаких проблем — всё запускается, всё работает, как обычно, в общем. BootRun отрабатывает, только опции успевай подставлять.
Проблема пришла, откуда не ждали: когда пришло время разворачиваться на Амазоне, тогда и вылезла.
Итак, дубль раз. Чуть ли не в первый раз запускаю задачу BootJar. Ярхив готов, деплоим… Готово! Сигнала нет, сыпет ошибки 302 + 404 (это авторизация не находит вью). Но это пока не понятно.
Отключаем Секурити — всё равно ничего не находит, кроме голимой статики, и то не всей, а только из webjars. ???
Дубль два. Догадываясь о несовместимости jsp и BootJar, пакуем BootWar. Деплоим… Не работает. Не помню точно, но примерно то же самое в результате.
Хм, странно. Запускаем BootJar локально — всё работает. Чудеса.
Выяснилось: Spring Boot слишком умный, он при запуске из каталога разработки даже релизного ярника всё равно все тащит из каталога разработки. Из другого запускаем — перестаёт работать. Фух! Ну хоть отлаживать можно.
Что и делам. Выясняется — ресурсы BootJar запакованные не из библиотек (webjars), а из проекта, не включаются в перечисление, и это, оказывается, по дизайну! Подробности здесь.
Вернее не так — есть спец-ресурсы в каталогах типа static/, public/. И они вроде находятся, если объявить. Но jsp не видит в упор хоть тресни. И дело не в том, что не там лежат. Оказалось, что Томкат (в нашем плохом случае), грузит jsp особым механизмом после редиректа. И сами jsp можно загрузить без рендеринга, если правильно задать их положение в настройках
spring.resources.static-locations
Но это нас не устраивает.
Оказалось, что при использования встроенного томката, ресурсы вью он грузит отдельно и в первую очередь своей старой встроенной логикой, которую Спрингисты настраивать не научились. А этой логике нужен либо архив Вар, либо он же распакованный (почему кстати при разработке нормально отрабатывает расположение webapp/), либо ресурсы из библиотек, которые прекрасно видны, если правильно упакованы в изначальных либах — нужно чтоб лежали в META-INF/resources, как в стандарте сервлетов. Последнее работает даже внутри BootJar. Удивительно.
Почему не сработал распакованный архив? Ё-маё, на амазоне он распакуется черти-куда, и приложение про это место ничего не знает, если не сказать. Но хардкодить пути — плохая привычка. Сам ярник запускается затем безо всякой распаковки, хотя вроде права позволяют распаковать прям на месте. Ну да ладно, способ пролетел.
Почему не работает способ с Вар-архивом? Ё-маё, Амазон решил, что лучше меня знает, что я буду грузить именно в яр-формате, хотя интерфейс заявлет о готовности съесть варник. Он этот варник переименовывает в ярник, умник такой. А Томкат не умничает, он смотрит расширение: не Вар — ну тогда, извините, это не мой случай.
В итоге корень деплоя не находится. И ресурсы оттуда тоже. Ресурсы из статики не грузятся, потому что ищутся в корне и ресурсных либах, а не в classpath.
Ладно, проблема понятна. Решение?
Было три варианта.
  • Сделать свой spring-загрузчик ресурсов. Вариант отпал, поскольку, как я уже сказал, Томкат отрабатывает jsp до их запуска.
  • Прокинуть загрузку в Томкат. Стал прикидывать: надо расширить контекст spring-а, прокинуть пути в контекст Томката, там ещё раза два переложить — непонятно, насколько сложно, и можно ли без изменения самого томката. Спрингисты не осилили, и я не хочу.
  • Вариант попроще — пакуем ресурсы в ресурсную либу в BootJar.

Вот о нём подробнее. Пихать всё в отдельный модуль, как предлагали здесь, не хотелось.
Делаем отдельной задачей в Gradle.
Создаём конфигурацию.
sourceSets {
    jsp {
        resources.source(sourceSets.main.resources);
        resources.srcDirs += ['src/main/webapp'];
    }
    jmh {
        .. ..
    }
}

Сама задача
task jsp(type: Jar, description: 'JSP Packaging') {
    archiveBaseName = 'jsp'
    group = "build"
    def art = sourceSets.jsp.output
    from(art) {
        exclude('META-INF')
        into('META-INF/resources/')
    }
    from(art) {
        include('META-INF/*')
        into('/')
    }
    dependsOn(processJspResources)
}

Задача processJspResources уже создана, её не надо делать. Ставим всё в зависимость и пакуем:
bootJar {
    dependsOn(jsp)
    bootInf.with {
        from(jsp.archiveFile) {
            include('**/*.jar')
        }
        into('lib/')
    }
}

Как добавить другим способом (прямым), не нашёл — подключить в зависимости конфиг jspImplementation самого же проекта — нельзя, а хотелось бы. Но если все же из другого модуля забирать, то вот так ещё делаем:
artifacts {
    jspImplementation jsp
}

Всё, теперь имеем ресурсную либу, которую по всем стандартам томкат должен грузить, и он грузит. Запускаем, как BootJar.
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_programmirovanie (Программирование), #_java, #_amazon_web_services, #_gradle, #_oblachnye_servisy (Облачные сервисы), #_aws_beanstalk, #_spring_boot, #_tomcat, #_tomcat_deploy, #_jsp, #_gradle, #_programmirovanie (
Программирование
)
, #_java, #_amazon_web_services, #_gradle, #_oblachnye_servisy (
Облачные сервисы
)
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 10-Июн 17:08
Часовой пояс: UTC + 5