Удаленная отладка в IntelliJ Idea

Временно «отдыхаю» от котлино-реакта. Перебросили меня на проект по доработкам отчетов на софтверной жире. Это такие плагины для Atlassian Jira. У нас они сейчас на 8 джаве с приправой из Atlassian SDK и с фронтом на Anguar-5.

Отчеты на Atlassian SDK это такая штука, где вы будете использовать циклы-в-цикле и никуда от этого не деться, благодаря такой «замечательной» штуке как Active Object. Фишка в чем — тут нет join-ов! Поэтому таблицы содержат избыточные ключи, для связок. Это значит что под капотом это выглядит примерно так: select * from table1 where table2_id  in (id1, id2 … idN) facepalm.jpg

Спасибо, что хоть на 8й джаве, где есть небольшое спасение от foreach{ foreach { foreach{}}} благодаря стримам (stream).

Вот сижу, рефакторю, мучаюсь от отсутствия отладки.  А потом думаю, а чего я собственно? Тема-то наверняка избитая. Списался с админом, погуглил решение и бинго! А вот и не бинго а жопа. Потому что все решения для дебагга касаются запуска томката при помощи батника catalina.bat, а у нас он запущен как сервис.

Делать нечего, будем скрещивать ежа с ужом. В каталоге bin томката лежит кроме catalina.bat еще service.bat, которым собственно и запускают сервис (в нем нет параметров для удаленной отладки).

В нем, где-нибудь в начале надо поставить сеттеры, где localhost:8000 — это адрес сервера и порт для отладки (рекомендуется 8000). Для локальной жиры так и оставить localhost.

set JPDA=jpda
set JPDA_TRANSPORT=dt_socket
set JPDA_ADDRESS=localhost:8000
set JPDA_SUSPEND=n
set JPDA_OPTS=-agentlib:jdwp=transport=%JPDA_TRANSPORT%,address=%JPDA_ADDRESS%,server=y,suspend=%JPDA_SUSPEND%

Затем, где идет создание и запуск сервера надо найти параметр —JvmOptions и в него добавить «%JPDA_OPTS%; Например так:

--JvmOptions "%JPDA_OPTS%; -Dcatalina.home=%CATALINA_HOME%;-Dcatalina.base=%CATALINA_BASE%;-D%ENDORSED_PROP%=%CATALINA_HOME%\endorsed;-Djava.io.tmpdir=%CATALINA_BASE%\temp;-Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager;-Djava.util.logging.config.file=%CATALINA_BASE%\conf\logging.properties;%JvmArgs%" ^

Потом, когда админ присылает радующую глаз картинку:

Идем в Idea и создаем настройку для удаленной отладки. Для этого в Run|Debug конфигурации прописываем адрес и порт сервера из переменной JPDA_ADDRESS.

Готово, вы великолепны!

p.s.

Fat jar и автозапуск web-приложения

Открываю новую рубрику — «рецепты». Во время поиска работы написал я небольшое веб-приложение и для его демонстрации выложил на «бесплатный» сервер амазона. Как получить себе такой сервер, можно почитать на хабре, а я хочу рассказать как используя SpringBoot и его fat jar можно легко установить свое приложение на линуксовый сервер. На примере моего приложения carservice. Нам понадобится доступ к серверу (любому, не обязательно у амазона), на который надо залить наш jar-ник.

  1. Проверить работает ли приложение, выполнив команду: java -jar /home/ubuntu/carservice.jar
  2. Создать файл carservice.service в папке /ets/systemd/system и прописать в нем следующее:
  3. [Unit]
    Description=carservice
    After=syslog.target
    
    [Service]
    User=carservice
    ExecStart=/home/ubuntu/carservice.jar
    SuccessExitStatus=143
    
    [Install]
    WantedBy=multi-user.target
    
  4. Стартовать сервис: service carservice start
  5. Проверить статус: systemctl -l status carservice
  6. Перезагрузить сервер.
  7. Все готово — вы великолепны! smile

Коктейль из Java, Kotlin и ReactJS

Итак, я сменил галеру место работы. И, неожиданно, технологии. Java есть, номинально, но на текущий момент, плотно уже 3 недели изучаю Kotlin в связке с ReactJS.

До этого я конечно слышал, про них, но не пробовал. По котлину пару обучающих видео посмотрел и вперед.

Первые впечатления: точка-с-запятой не нужна, типы указываем после переменной, тернарный оператор урезан и стал «элвис» оператором, статических полей нет, финальная и нефинальная переменные обозначаются val и var, функции заменили методы, все классы по-умолчанию финальные. Аааааа-ааа-а!!!

Пример:

fun getPrintTemplate(data: Map<String, Any?>, metadata: MutableList<String> = mutableListOf()): MutableList<String> {
 data.forEach { entry ->
            val value = entry.value
            if (value is Collection<*> && value.isNotEmpty()) {
                (value.first() as Map<String, Any?>)
                        .keys
                        .forEach { subKey -> metadata.add("${entry.key}.$subKey") }
            }
            if (value is Map<*, *>) getPrintTemplate(value as Map<String, Any?>, metadata)
}
    return metadata
}

По реакту — это даже не фреймворк, напрямую не пишем? а под котлин это выглядит как работа с обычными классами.
Вот например создаем элемент:

fun RBuilder.downloadLink(fileName: String, dataFunc: suspend () -> String, body: ((RBuilder).() -> Unit)? = null) {
    a {
        attrs.onClickFunction = {
            async {
                val base64data = dataFunc()
                downloadFile(base64data, fileName).invoke()
            }
        }
        if (body != null) {
            body()
        } else {
            +fileName
            +" "
            icon("download")
        }
    }
}

А потом обращаемся к нему:

    row{
        downloadLink(attach[Attachment.displayName], dataFunc = { handleDownload() })
    }

 

В общем как новый язык изучать. Угораздило жеж ))

Ароматный Java

Java это не только язык, но и кофе. Не даром чашка горячего напитка является его логотипом.

Наконец-то пришла посылка с тру кофе для джависта  cool