У меня есть REST API на основе Java (через Jersey 1.18), который я развернул в приложении AppEngine вместе с интерфейсом React.
Мой web.xml объявляет два сервлета:
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
...
<servlet>
<servlet-name>react</servlet-name>
<jsp-file>/index.html</jsp-file>
</servlet>
<servlet-mapping>
<servlet-name>react</servlet-name>
<url-pattern>/login</url-pattern>
...
</servlet-mapping>
...
<servlet>
<servlet-name>jsp</servlet-name>
<servlet-class>org.apache.jasper.servlet.JspServlet</servlet-class>
</servlet>
<jsp-config>
<taglib>
<taglib-uri>http://www.myapp.com/customtags</taglib-uri>
<taglib-location>/WEB-INF/custom-tags/UserRefTag.tld</taglib-location>
</taglib>
<jsp-property-group>
<url-pattern>*.jsp</url-pattern>
<page-encoding>UTF-8</page-encoding>
</jsp-property-group>
</jsp-config>
и, конечно же, фильтр Джерси:
<filter>
<filter-name>jersey</filter-name>
<filter-class>com.sun.jersey.spi.container.servlet.ServletContainer</filter-class>
<init-param>
<param-name>com.sun.jersey.config.property.packages</param-name>
<param-value>com.myapp.servlets;com.myapp.tasks;com.wordnik.swagger.jersey.listing
</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.provider.packages</param-name>
<param-value>com.myapp.audit;com.myapp.filters</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.JSPTemplatesBasePath</param-name>
<param-value>/WEB-INF/jsp</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.config.property.WebPageContentRegex</param-name>
<param-value>/(js|css|(WEB-INF/jsp)|_ah|ipn|woff|woff2|ui|json|html)/.*</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerRequestFilters</param-name>
<param-value>com.myapp.audit.AuditLogInterceptor</param-value>
</init-param>
<init-param>
<param-name>com.sun.jersey.spi.container.ContainerResponseFilters</param-name>
<param-value>com.myapp.filters.CorsFilter</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>jersey</filter-name>
<url-pattern>/tasks/*</url-pattern>
...
</filter-mapping>
Я указал в appengine-web.xml соответствующие статические ресурсы:
<static-files>
<include path = "/static/**" expiration = "10s"/>
<!-- react ui resources (eg: manifest.json etc) -->
<include path = "*.html" expiration = "10s"/>
<include path = "*.json" expiration = "10s"/>
<include path = "*.js" expiration = "10s"/>
</static-files>
Таким образом, в идеале, когда пользователь достигает конечной точки, такой как /login, он должен транслироваться в реагирующий сервлет и направляться в index.html, которое является реагирующим приложением. Затем ReactRouter должен включиться и отобразить страницу входа. Все статично, пока не проверит сеанс или что-то в этом роде.
Все это прекрасно работает в devserver. Когда я загружаю /login, он отображает мое приложение для реагирования. Когда реагирующее приложение вызывает серверные конечные точки REST, все они работают.
Затем я поставил его на appengine (стандартная среда), и это совсем другая история. Все конечные точки REST отвечают, но реагирующее приложение не запускается. Все, что я получаю, это: Error /login или подобное.
Когда я смотрю в логах appengine, я вижу это:
:WARN:oaj.EmbeddedServletOptions:RequestDA26342E: The scratchDir you specified: [/base/data/home/apps/g~myapp-alpha/alpha2.419176782209598562/jsp] is unusable
Погуглив, эта ошибка, похоже, связана с правами доступа к каталогу в WebContainer, но это все скрыто от меня, потому что это appengine.
Что на самом деле означает эта ошибка? В чем проблема? Как я могу решить эту проблему?




После долгих взломов выяснилось, что указание HTML-файла в элементе вызывало проблемы.
Какой бы веб-контейнер appengine ни использовал, он пытался его скомпилировать, но предполагается, что appengine предварительно скомпилирует все JSP при загрузке, поэтому ему не нужно этого делать. Их установка явно не справляется с этим.
Исправление заключалось в том, чтобы переместить и переименовать /index.html в /WEB-INF/jsp/index.jsp
Тогда все было совершенно счастливо.