Как заставить JSF работать с приложением spring-boot в контейнере docker?

#jsf #docker #spring-boot

#jsf #docker #spring-boot

Вопрос:

У меня есть приложение, созданное с помощью spring-boot 1.4.0 и JSF 2.2 (Mojarra 2.2.13), работающее на встроенном tomcat (8.5).

Когда я запускаю приложение локально, оно работает нормально — независимо от того, запускаю ли я его из своей IDE, с mvn spring-boot:run помощью или java -jar target/myapp.jar

Однако, когда я запускаю приложение внутри контейнера docker (используя docker 1.12.1), все работает, за исключением страниц JSF. Например, страницы spring-boot-actuator /health работают просто отлично, но при попытке доступа /home.xhtml (страница JSF) Я получаю:


Страница с ошибкой белой метки

Это приложение не имеет явного сопоставления для /error , поэтому вы рассматриваете это как запасной вариант.

Ср. Окт. 12 09:33:33 GMT 2016 Произошла непредвиденная ошибка (тип = Не найден, статус = 404). /home.xhtml Not Found in ExternalContext as a Resource


Я использую io.fabric8:docker-maven-plugin для создания образа docker (на основе alpine с openjdk-8-jre), который включает в себя артефакт сборки /maven внутри контейнера docker и java -jar /maven/${project.artifactId}-${project.version}.jar для запуска приложения.

Я использую порт 9000 вместо стандартного порта tomcat (8080), и это также отображается в образе docker.

Я уже сравнил как локальный jar, так и тот, который включен в контейнер docker, и оба они имеют одинаковое содержимое.

Любая помощь будет оценена. Заранее спасибо

Ответ №1:

Файлы XHTML и остальные файлы JSF были помещены в неправильный каталог.

По крайней мере, при использовании <packaging>jar</packaging> кажется, что все содержимое JSF должно быть помещено под src/main/resources/META-INF , а src/main/webapp не там, где большинство IDE автоматически размещают его.

Когда материал JSF находится в src/main/webapp нем, он не включается (или не в нужном месте) в файл jar с переупаковкой spring-boot.

Сейчас мой src/main/resources выглядит так:

 src
└── main
    └── resources
        ├── application.yml
        └── META-INF
            ├── faces-config.xml
            └── resources
                ├── administration
                │   └── userlist.xhtml
                ├── css
                │   └── default.css
                ├── images
                │   └── logo.png
                └── home.xhtml
  

Ответ №2:

У меня была точно такая же проблема. Запуск приложения Spring Boot непосредственно из maven или из упакованного файла WAR работал нормально, но запуск его из контейнера Docker приводил к той же проблеме.

На самом деле, проблема для меня заключалась в том, что доступ к динамическим ресурсам (JSP и т.п.) Всегда приводил к попытке показать страницу с ошибкой, которую не удалось найти, и поэтому был возвращен 404, но статический контент был возвращен правильно.

Звучит глупо, но для меня оказалось, что важно, вызываете ли вы упакованный файл войны «.war» или «.jar» при его запуске. Я использовал пример Docker для Spring Boot, который (по какой-то причине) называет файл WAR «app.jar «. Если вы это сделаете, вы столкнетесь с этой проблемой в контейнере Docker. Если вместо этого вы назовете его «app.war», он будет работать нормально.

Кстати, это не имеет никакого отношения к Docker. То же самое происходит, если вы пытаетесь запустить приложение непосредственно на хосте, когда оно имеет расширение .jar (если вы не запускаете его в месте, где необходимые ресурсы лежат в извлеченном виде).

Запуск моего приложения с

 java -Duser.timezone=UTC -Djava.security.egd=file:/dev/./urandom -jar application.jar
  

приводит к ошибке. Переименование из .jar в .война и использование

 java -Duser.timezone=UTC -Djava.security.egd=file:/dev/./urandom -jar application.war
  

заставило его работать.

Ответ №3:

Что сработало для меня, так это копирование папки webapp в META-INF при добавлении ресурсов

 <resource>
  <directory>src/main/webapp</directory>
  <targetPath>META-INF/resources</targetPath>
</resource>
  

а затем добавьте изменить DocumentRoot на путь, по которому он доступен в контейнере docker:

 @Bean
public WebServerFactoryCustomizer<ConfigurableServletWebServerFactory>
  webServerFactoryCustomizer() {
    return factory -> factory.setDocumentRoot(new File("/workspace/META-INF/resources"));
}
  

теперь я могу использовать страницы jsf при использовании spring-boot:build-image и упаковке jar

ps: у меня все еще была куча исключений, которые исчезли после обновления spring boot liquibase до новейшей версии, но я думаю, что это не относится к этой теме