NPE при регистрации сервлетов для развертывания в единый WAR-файл

Здравствуйте! При развертывании в Jelastic возникла проблема с REST как я правильно понял из за того что в single-war-web.xml не были зарегистрированы сервлеты отвечающие за REST API. Следуя документации https://doc.cuba-platform.com/manual-7.0-ru/servlet_registration.html#servlet_registration_single_war я программно зарегистрировал все сервлеты и фильтры. Но теперь при запуске приложения на хостинге получаю NPE. Подскажите пожалуйста чем причина и что я делаю не так. Версия платформы 7.0.5
Лог ошибки catalina.txt (39.2 КБ)
Код класса регистрации сервлетов

public class CustomWebListener implements ServletContextListener
{
    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        ServletContext servletContext = servletContextEvent.getServletContext();
        registerApplicationServlet(servletContext);
        registerCubaDispatcherServlet(servletContext);
        registerCubaRestApiServlet(servletContext);
        registerCubaHttpFilter(servletContext);
        registerDelegatingFilterProxy(servletContext);
    }

    @Override
    public void contextDestroyed(ServletContextEvent sce) {
    }

    protected void registerApplicationServlet(ServletContext servletContext) {
        ServletRegistration.Dynamic servletReg = servletContext.addServlet("app_servlet", CubaApplicationServlet.class);
        servletReg.setLoadOnStartup(0); //ошибка тут
        servletReg.setAsyncSupported(true);
    }

    protected void registerCubaDispatcherServlet(ServletContext servletContext) {
        ServletRegistration.Dynamic servletReg = servletContext.addServlet("dispatcher", CubaDispatcherServlet.class);
        servletReg.setLoadOnStartup(1);
    }

    protected void registerCubaRestApiServlet(ServletContext servletContext) {
        ServletRegistration.Dynamic servletReg = servletContext.addServlet("app_servlet", CubaRestApiServlet.class);
        servletReg.setLoadOnStartup(2);
        servletReg.addMapping("/dispatch/*", "/*", "/rest/*");
    }

    protected void registerCubaHttpFilter(ServletContext servletContext) {
        FilterRegistration.Dynamic filterReg = servletContext.addFilter("cuba_filter", CubaHttpFilter.class);
        filterReg.setAsyncSupported(true);
        filterReg.addMappingForUrlPatterns(null, true,"/*");
    }

    protected void registerDelegatingFilterProxy(ServletContext servletContext) {
        FilterRegistration.Dynamic filterReg = servletContext.addFilter("restSpringSecurityFilterChain", DelegatingFilterProxy.class);
        filterReg.setInitParameter("contextAttribute", "org.springframework.web.servlet.FrameworkServlet.CONTEXT.rest_api");
        filterReg.setInitParameter("targetBeanName", "springSecurityFilterChain");
        filterReg.addMappingForUrlPatterns(null, true,"/rest/*");
    }
}

Добрый день,

  1. REST API при развертывании в Single WAR должно работать “из коробки”, без дополнительных программных регистраций. Если оно не работает, то это баг.
    В моем проекте (правда на 6.10) REST API работает без проблем с Single WAR.

  2. В вашем приложенном логе ну прямо перед NPE выполняется код регистрации REST API:

2019-09-19 12:37:16.620 INFO  [main] com.haulmont.restapi.sys.SingleAppRestApiServlet - Initializing Servlet 'rest_api'
2019-09-19 12:37:16.620 DEBUG [main] com.haulmont.restapi.sys.SingleAppRestApiServlet - Servlet with name 'rest_api' will try to create custom WebApplicationContext context of class 'com.haulmont.cuba.core.sys.CubaXmlWebApplicationContext', using parent context [com.haulmont.cuba.web.sys.singleapp.SingleAppWebContextLoader$1@6d244c88, started on Thu Sep 19 12:37:10 UTC 2019]
2019-09-19 12:37:16.621 DEBUG [main] com.haulmont.restapi.sys.SingleAppRestApiServlet$1 - Refreshing WebApplicationContext for namespace 'rest_api-servlet'
2019-09-19 12:37:18.013 DEBUG [main] com.haulmont.restapi.sys.SingleAppRestApiServlet - Detected CommonsMultipartResolver
2019-09-19 12:37:18.017 DEBUG [main] com.haulmont.restapi.sys.SingleAppRestApiServlet - Detected CommonsMultipartResolver
2019-09-19 12:37:18.020 DEBUG [main] com.haulmont.restapi.sys.SingleAppRestApiServlet - Published WebApplicationContext of servlet 'rest_api' as ServletContext attribute with name [org.springframework.web.servlet.FrameworkServlet.CONTEXT.rest_api]
2019-09-19 12:37:18.020 DEBUG [main] com.haulmont.restapi.sys.SingleAppRestApiServlet - enableLoggingRequestDetails='false': request parameters and headers will be masked to prevent unsafe logging of potentially sensitive data
2019-09-19 12:37:18.020 INFO  [main] com.haulmont.restapi.sys.SingleAppRestApiServlet - Completed initialization in 1400 ms
2019-09-19 12:37:18.029 ERROR [main] com.haulmont.cuba.web.sys.singleapp.SingleAppWebContextLoader - Error initializing web servlets
java.lang.NullPointerException: null

Исходя из названия SingleAppRestApiServlet - этот класс и есть специализированный сервлет для REST API + single war.

Спасибо за ответ. Попробовал развернул без программной регистрации сервлетов. Сервлет действительно инициализируется из коробки.

24-Sep-2019 08:46:49.079 INFO [main] org.apache.catalina.core.ApplicationContext.log Initializing Spring RemotingServlet 'remoting'
24-Sep-2019 08:46:54.534 INFO [main] org.apache.catalina.core.ApplicationContext.log Initializing Spring SingleAppDispatcherServlet 'dispatcher'
24-Sep-2019 08:46:55.602 INFO [main] org.apache.catalina.core.ApplicationContext.log Initializing Spring SingleAppRestApiServlet 'rest_api'

Но почему то при REST запросах я получаю 301 (Moved Permanently) ответ? Это связано с неправильной настройкой на хостинге? Или нужно в приложении чтото где то поправить?

Здравствуйте, @gumax1962

при REST запросах я получаю 301 (Moved Permanently) ответ

Встроенные REST API endpoint’ы имеют фиксированные адреса, поэтому, скорее всего, формируется неправильный запрос. Убедитесь, что формируется следующий адрес запроса:

http://${host}:${port}/${appUrl}/rest/v2/***,

где ${appUrl} - адрес веб-приложения (по умолчанию - app). Настраивается свойством cuba.webAppUrl.

В случае, если запросы идут через portal модуль, то по умолчанию appUrl - app-portal

Здравствуйте, @tsarev ! Попробовал поменять конфигурацию не помогает.

URL запроса http://admin.go-planb.ru/app/rest/v2/oauth/token

При таком запросе 301 код
Если добавляешь порт вообще ничего не грузит
Конфигурация:

'cuba.webHostName'                  : 'admin.go-planb.ru',
'cuba.webAppUrl'                        : 'app',
'cuba.webPort'                             :'8080']

Код 301 не приходит сам по себе, это редирект на какой-то другой URL.
Куда вас перенаправляет с указанного URL запроса?
Появляются ли в момент запроса какие-нибудь сообщения в любом из журналов сервера?

Я не могу понять на какой url меня перенаправляет
В журнале localhost_access появляются записи но они не сильно информативны

10.50.3.12 - - [30/Sep/2019:07:39:49 +0000] "GET /app-core/remoting/health HTTP/1.1" 301 -
10.50.3.12 - - [30/Sep/2019:07:40:59 +0000] "POST /app/rest/v2/oauth/token HTTP/1.1" 301 -
10.50.3.12 - - [30/Sep/2019:07:41:40 +0000] "POST /admin/rest/v2/oauth/token HTTP/1.1" 301 -

В последнем запросе пробовал поставить свойство web.appUrl=admin все равно такая же проблема.
В другом проекте у нас в компании указано свойство

'cuba.webAppUrl': 'http://osod.app.infinnity.ru/app', 

И все замечательно работает. Пробовал таким образом выставить свойство в этом проекте тоже не помогло…Может на jelastiс какие то настройки надо выставлять?

Вот лог развертывания catalina.txt (28.5 КБ)

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

Чтобы посмотреть куда идет редирект, можно вызвать запрос из командной строки утилитой curl:

$ curl -X POST -v "http://google.com"
...
< HTTP/1.1 301 Moved Permanently
< Location: http://www.google.com/
...
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8">
<TITLE>301 Moved</TITLE></HEAD><BODY>
<H1>301 Moved</H1>
The document has moved
<A HREF="http://www.google.com/">here</A>.
</BODY></HTML>

Вот здесь видно что происходит редирект на http://www.google.com/

10.50.3.12 - - [30/Sep/2019:07:41:40 +0000] “POST /admin/rest/v2/oauth/token HTTP/1.1” 301 -

Откуда берется этот запрос, это вы посылаете?

Далее, по логам я вижу что ваше приложение деплоится в корневом контексте (ROOT):

30-Sep-2019 07:37:44.730 INFO [main] org.apache.catalina.startup.HostConfig.deployWAR Deploying web application archive [/opt/tomcat/webapps/ROOT.war]

Скорее всего тогда ваше приложение доступно сразу по “/” и часть “/app” из URL-ов нужно удалить.

И свойство cuba.webAppUrl должно равняться “http://admin.go-planb.ru/

Спасибо. Вот этот вариант сработал