Наше JEE приложение сделало скачок версии GWT с 1.7 сразу до 2.6.1. Когда-то были небольшие танцы с бубном для того, чтобы в среде разработки IntelliJ Idea настроить возможность отладки клиентской части. Отладка заключается в возможности ставить точки останова (breakpoint-ы) в Java-коде, но попадать в них из браузерного JavaScript-а, сгенерированного GWT из Java-кода. После обновления версии GWT старая конфигурация запуска отладки работать перестала, и мне пришлось познакомиться с GWT Super Dev Mode (SDM). После этого «знакомства» я понял, что выше упомянутые «танцы» были на самом деле предельно простой и понятной настройкой, по крайней мере, в сравнении с SDM. Надеюсь, кому-то эта статья очень поможет сэкономить пару-тройку дней блужданий по форумам и избавит от нескольких новых седых волос. В статье я расскажу про опыт запуска режима SDM в следующем окружении: IntelliJ Idea 14, JBoss EAP 6, GWT 2.6.1 с применением в проекте GWT RPC, браузер Chrome. Несмотря на то, что при релизе Idea 14 сообщили о доработках касательно отладки в GWT, думаю, что для версии 13 всё нижеописанное также применимо. Используемый сервер приложений также вряд ли как-то влияет на настройку SDM. Насчет версий GWT: для 2.6.0 применимо почти один-в-один, то же касается и 2.7.0 (сам не проверял, вычитал в Сети по ходу проведения исследований).
Старый добрый режим отладки теперь практически не поддерживается в GWT, его место занял режим Super Dev Mode. Этот режим предполагает запуск специфического сервера приложений, так называемого Code Server, который несет ответственность за развертывание исходного Java-кода и сопоставление его с JavaScript-ом. В большинстве источников описывается развертывание вашего приложения под управлением Code Server и работа непосредственно с ним. Т.к. я использую в качестве среды разработки IntelliJ Idea, то предполагается, что мое приложение будет запущено и развернуто прямо в ней. Но в JEE разработчики обычно стараются работать с окружением, максимально приближенном к промышленному, а запуск промышленного сервера «из под Idea» — нонсенс. Таким образом, возникает дилемма: Code Server запущен в среде разработки, а сервер приложений запущен на отдельном компьютере — как их «подружить»? В принципе, в Сети есть вся нужная информация, но она разрознена, противоречива, а есть даже ответ на StackOverflow, имеющий множество «плюсов», но при этом неверный. Исходя из этих фактов, а также понимая насколько в общем и целом непросто запустить SDM, я и решил написать это руководство.
ВНИМАНИЕ! По завершении отладки в режиме GWT SDM следует откатить изменения в .gwt.xml («devModeUrlWhitelistRegexp») и пересобрать приложение!
Общая часть
Старый добрый режим отладки теперь практически не поддерживается в GWT, его место занял режим Super Dev Mode. Этот режим предполагает запуск специфического сервера приложений, так называемого Code Server, который несет ответственность за развертывание исходного Java-кода и сопоставление его с JavaScript-ом. В большинстве источников описывается развертывание вашего приложения под управлением Code Server и работа непосредственно с ним. Т.к. я использую в качестве среды разработки IntelliJ Idea, то предполагается, что мое приложение будет запущено и развернуто прямо в ней. Но в JEE разработчики обычно стараются работать с окружением, максимально приближенном к промышленному, а запуск промышленного сервера «из под Idea» — нонсенс. Таким образом, возникает дилемма: Code Server запущен в среде разработки, а сервер приложений запущен на отдельном компьютере — как их «подружить»? В принципе, в Сети есть вся нужная информация, но она разрознена, противоречива, а есть даже ответ на StackOverflow, имеющий множество «плюсов», но при этом неверный. Исходя из этих фактов, а также понимая насколько в общем и целом непросто запустить SDM, я и решил написать это руководство.
Доработки и настройка
- Во все .gwt.xml добавить строчку
<add-linker name="xsiframe"/>
Без нее SDM работать не будет. В GWT 2.7 это сконфигурировано по умолчанию, поэтому можно не добавлять. Можно собирать с этим параметром и на промышленный сервер. - Во все .gwt.xml добавить строчку
<set-configuration-property name="devModeUrlWhitelistRegexp" value="http://192\.168\.1\.1(:\d+)?/.*" />
В ней указать IP-адрес компьютера разработчика, на котором будет запущен Code Server. При сборке приложения для промышленного сервера, этот параметр желательно удалить/закомментировать. - Для версии GWT 2.6.0 во все .gwt.xml добавить строчку
<set-configuration-property name="devModeRedirectEnabled" value="true"/>
- Если вы используете GWT RPC, то во всех наследниках RemoteServiceServlet следует переопределить метод getCodeServerPolicyUrl. Я сделал это так:
/** * Метод переопределен исключительно для отладки в режиме GWT SDM. Для того, чтобы сервер заработал в режиме * отладки GWT SDM следует указать системные свойства gwt.codeserver.port (стандартное св-во GWT SDM) и * gwt.codeserver.host (специфическое св-во нашей Системы). После указания этих свойств и перезапуска сервера * файлы .gwt.rpc будут подтягиваться с указанного хоста, на котором должен быть запущен GWT Code Server. Это * требуется для того, чтобы отлаживаемый клиент имел те же версии скомпилированных типов, что и сервер. * ВНИМАНИЕ! Не допускать указание этих свойств на промышленных серверах! */ protected String getCodeServerPolicyUrl(String strongName) { String port = System.getProperty("gwt.codeserver.port"); String host = System.getProperty("gwt.codeserver.host"); if (port == null || port.trim().isEmpty() || host == null || host.trim().isEmpty()) { return super.getCodeServerPolicyUrl(strongName); } return "http://" + host + ":" + port + "/policies/" + strongName + ".gwt.rpc"; }
Из содержания комментария к методу можно понять, что разработчики GWT предусмотрели возможность указания только для номера порта, на котором находится Code Server, но не сетевого адреса, т.е., судя по всему, они не предполагали, что сервер приложений и Code Server могут быть разными компьютерами. - Указать значения системных свойств "gwt.codeserver.host" и "gwt.codeserver.port" для тестового сервера приложений. Это можно сделать путем указания параметров старта JVM -Dgwt.codeserver.host= -D=gwt.codeserver.port=, либо с использованием специфических для вашего сервера инструментов. В JBoss EAP для этого можно добавить в конфигурационный файл (standalone*.xml, domain.xml) блок <system-properties> с <property name="" value=""/> в нём. Убедитесь в том, что после запуска Code Server-а у вас есть доступ с сервера приложений по указанным адресу и порту (telnet «проваливается»).
- Добавить в Idea новую конфигурацию GWT Configuration и указать в ней:
- Включить чекбокс «Use Super Dev Mode»
- Если после старта отладки увидите в логе «log4j:ERROR», то в «VM options» добавьте -Dlog4j.ignoreTCL=true. Возможно, вам это не понадобится, у меня возникли какие-то коллизии GWT с проектными библиотеками логирования
- В «Dev Mode parameters» добавить -bindAddress 192.168.1.1, где указать IP-адрес Code Server (компьютера разработчика). По умолчанию CodeServer слушает localhost или 127.0.0.1, но если сервер приложений находится на другом компьютере, то он не сможет получить доступ к CodeServer-у по таким адресам, поэтому следует указать CodeServer-у, чтобы он прослушивал адрес, доступный извне.
- В GWT 2.6.1 есть глюк, проявляющийся при запуске CodeServer-а в Idea (возможно, его нет при независимом от среды разработки запуске). Проблема заключается в том, что осуществляется попытка повторно создать папки для временных файлов при развертывании приложения, которая завершается ошибкой, приводящей к остановке CodeServer-а. Чтобы решить эту проблему мне пришлось пропатчить библиотеку gwt-codeserver.jar, в которой в классе CompileDir я закомментировал строчку
throw new UnableToCompleteException();
в самом конце файла. Исходники находятся в самом gwt-codeserver.jar; вытаскиваем .java, изменяем, компилируем, закидываем .class обратно в gwt-codeserver.jar. Библиотека нужна только разработчику, а на промышленном сервере (да и на тестовом тоже) ей делать нечего, так что поводов для беспокойства по поводу такого бесцеремонного обращения нет.
Запуск
- Пересобрать приложение и запустить ваш сервер
- Запустить CodeServer (конфигурацию GWT Configuration) в режиме Debug
- Открыть в браузере Chrome адрес, указанный в логе CodeServer-а (http://192.168.1.1:9876/)
- Перенести в «Избранное» браузера кнопки «Dev Mode On» и «Dev Mode Off»
- Наше приложение настроено так, что при входе в Систему открывается окно с отключенными элементами управления браузера, в т.ч. «Избранное». Если вы поступаете так же, то измените ваш HTML так, чтобы в клиентской части были доступны «Dev Mode On» и «Dev Mode Off»
- Открываем клиентскую часть в браузере и нажимаем «Dev Mode On», затем жмем кнопку «Compile»
- Ждем пока на стороне Code Server-а завершится компиляция. После этого страница будет перезагружена.
- После перезагрузки страницы нажатием F12 в Chrome открываем стандартные инструменты разработчика, в которых открываем вкладку Sources. В древе слева (вкладка Sources внутри вкладки Sources) видно, что в данный момент есть ресурсы, загруженные не только с основного сервера приложений, но и с CodeServer. Жмем CTRL+P, ищем Java-класс, который собираемся отлаживать, ставим в нем Breakpoint.
ВНИМАНИЕ! По завершении отладки в режиме GWT SDM следует откатить изменения в .gwt.xml («devModeUrlWhitelistRegexp») и пересобрать приложение!