Blog

Снова в деле

Ура! Я опять программирую на Kotlin. Скучал, да. После последней записи, прошло 4 года, где я работал на русско-американскую компанию.  Там была только унылая джава. Хоть и 17-я, но все равно, чувствовал себя динозавром. Но, потом проект закончился, и я 1,5 мес искал работу. К счастью, нашел прекрасный вариант — дубайский финтех-стартап. Оказывается я заматерел, сразу взял быка за рога и за пару месяцев сделал отличный микросервис  — workflow-engine aka state machine. А заодно spring-boot-starter либу для работы со всем этим добром. Страшно собой горжусь, но и это еще не все. Через 3 месяца увольняется тех-лид и я вижу, что это шанс для меня. Обговариваю с хэдами и мне делают предложение, от которого я не смог отказаться)) Короче, я уже без 5 минут Head of development, но писать код не перестаю, что меня радует.

Вляпался в Google Web Toolkit

Gwt — то еще дерьмище. На этом можно было бы закончить, но я обосную.

Чтобы нарисовать форму надо создать 100500 классов. Но это полбеды. Чтобы запускать свои сервисы, нужны прокладки в виде фасадов. Надо создавать кучу интерфейсов, их требуют все эти презентеры, виджеты, вьюхи, фасады. На-хе-ра столько телодвижений? Наверно это был прорыв в 2008 году, но в 2021 и особенно после реакта, плачу кровавыми слезами.

Шла 3-я неделя копания в легаси, проект живет с 2010 года, в нем одних только java файлов — 7500 штук!

Но работа есть работа, тем более если за нее хорошо платят.

Проект «Ментор»

Внезапно обнаружился у меня неплохой талант обучения, наставничества. Паре человек я просто решил помочь на пути становления программиста. Все прошло очень круто, получил массу удовольствия, а парни получили профессию. В общем-то я давно заметил у себя тягу к наставничеству (может ещё институтский преподавательский бэкграунд сказался), но не придавал этому значения. Когда на джавараше опубликовал фотку своего рабочего места и сообщил, что мол вот уже после курсов работаю — в личку стали стучаться люди с просьбой поделиться опытом как студенту найти свою первую работу. Этот вопрос мы тоже рассмотрим yes

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

Чем хорошо наставничество — да всем. На онлайн курсах не пишут о нюансах работы. Есть такие знания, которые сразу даже не вспомнишь, но они всплывают во время беседы и демонстрации. На занятиях мы будем заполнять пробелы и шлифовать навыки.

Если вы уже прошли обучение Java core — добро пожаловать на борт. Круто, если Spring, REST и SQL — не просто слова, а вполне освоенные инструменты. Знание этого покрывает потребности 80% рынка. Если нет, то нам просто придется дольше продвигаться к правой части схемы:

Если ВЫ ЗДЕСЬ, значит пришли по адресу smile

з.ы. Скоро доделаю отдельный раздел, где опишу условия.

upd: доделал, не прошло и года -> mentor.kapion.ru

Stay tuned.

Преобразование в PDF/A с помощью Jodconverter

Стоит задача сделать возможность сохранения текущей страницы в PDF. Обычное такое преобразование, куча библиотек на эту тему (например: iText, PDFbox, даже микросервис pdf-bot), если бы не одно «НО»: формат должен быть PDF/A. Т.е. формат для долгосрочного хранения, содержащий в теле файла шрифты, метаинформацию, цветовой профиль и т.д. — в общем все, что нужно для корректного отображения, независимо от платформы.

Библиотека Jodconverter является прослойкой между приложением и OpenOffice (или LibreOffice), который умеет конвертировать в PDF/A.

Стандартное преобразование:

    public static void main(String[] args) throws OfficeException {
        OfficeManager officeManager = LocalOfficeManager.make();
        DocumentConverter converter = LocalConverter.make(officeManager);

        System.out.println("officeManager start");
        officeManager.start();
        try {
            System.out.println("convert start");

            File inputFile = new File("c:/jServers/1/www1.html");
            File pdfFile = new File("c:/jServers/test_W.pdf");


            DocumentFormatRegistry registry = converter.getFormatRegistry();
            DocumentFormat htmlFormat = registry.getFormatByExtension("html");
            DocumentFormat pdfFormat = registry.getFormatByExtension("pdf");

            converter.convert(inputFile).as(htmlFormat).to(pdfFile).as(pdfFormat).execute();

            System.out.println("convert end");
        } catch (OfficeException e) {
            e.printStackTrace();
        } finally {
            if (officeManager.isRunning())
                officeManager.stop();
        }
    }

В результате мы получим обычный pdf.

Для нашей задачи необходимо включить настройку при экспорте. Вот так это выглядит в самом OpenOffice:

Для этого в коде мы должны создать свой собственный формат.

    private static DocumentFormat getDocumentFormatPDFA() {
        final int PDFX1A2001 = 1;

        final Map<String, Integer> pdfOptions = new HashMap<>();
        pdfOptions.put("SelectPdfVersion", PDFX1A2001);

        return DocumentFormat.builder()
                .inputFamily(DocumentFamily.TEXT)
                .extension("pdf")
                .mediaType("pdf")
                .storeProperty(DocumentFamily.TEXT, "FilterData", pdfOptions)
                .storeProperty(DocumentFamily.TEXT, "FilterName", "writer_pdf_Export")
                .unmodifiable(false)
                .build();
    }

Соответственно формат pdfFormat будет:

 DocumentFormat pdfFormat = getDocumentFormatPDFA();

В данном примере я преобразую в самый распространенный формат PDF/X-1a. Для других, используйте один из вариантов ниже:

final int PDFXNONE = 0;
final int PDFX1A2001 = 1;
final int PDFX32002 = 2;
final int PDFA1A = 3;
final int PDFA1B = 4;

А теперь можно проверить на валидаторе https://pdfrecover.herokuapp.com/pdfaconvert/

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

Удаленная отладка в 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.

Как удалить аккаунт Amazon AWS

Вот только что удалил аккаунт, пользовался почти год, но всегда помнил, что в феврале карета превратится в тыкву придет час расплаты в виде $300).

Официальные требования к закрытию аккаунта на амазоне суть которых сводится к простому — заплати бабло и спи спокойно.

На странице биллинга у меня $0.00, потому что я хитрая жопа пользовался бесплатным сервером на год (AWS Free Usage Tier)

Переходим в панель AWS Management Console в Sevices-EC2:

В панели EC2 пробегаемся по всей боковой менюшке и удаляем instance, security group, Key Pairs и т.д. Надо вспомнить где и что вводил/создавал — это нужно все грохнуть и потом получиться закрыть аккаунт.

Когда все интстансы перевели в статус: terminated идем в My account:

И мотаем вниз до красной кнопки Close account. Ставим галку и жмем кнопку.

Готово. Ждем письмо с подтверждением smile

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