Изменение версии java в Ubuntu
Рассматриваемая система — Ubuntu 22.04. Нужно сделать так, чтобы была возможность одной командой изменить дефолтную версию java. На самом деле оно уже есть, и чтобы изменить версию java в ubuntu, нужно лишь использовать команду: Эта команда изменит ссылку файла /usr/bin/java, которая ссылается на одну из установленных версий java (обычно в директории /usr/lib/jvm). Также переменная JAVA_HOME, которая по-умолчанию ссылается на /usr/bin/java, попадёт в выбранную версию. Всё работало до того момента, когда мне понадобилось добавить GraalVm. Во-первых, GraalVm не появляется в списке update-alternatives; Во-вторых, даже если его туда добавить, то например, Intellij Idea при попытке компилляции проекта выдает ошибку: ‘gu’ tool was not found in your JAVA_HOME.This probably means that the JDK at ‘/usr/bin/java’ is not a GraalVM distribution. Проблема с граалем заключается в том, что Idea пытается найти другие бинарные файлы грааля в одной директории с файлом java из $JAVA_HOME, но их ведь нету в /usr/bin. Проблема решается тем, чтобы удалить…
Логгирование JMS сообщений
Различные способы логгирования JMS сообщений: 1. Логгирование внутри конвертора (Плюс в том, что будет логгироваться тело сообщения как есть. Если сообщение невозможно распарстить, то оно тоже залоггируется (если конечно это TextMessage)): 2. Логгирование внутри jmsTemplate при отправке (Тоже тело сообщения как есть): 3. Логгирование внутри @JmsListener’а (Тоже тело сообщения как есть): 4. Установка уровня логгирования для входящих сообщений (Минус в том, что логгируется объект Message целиком, и тело сообщения может просто не влезть в максимальную длину записи лога):
Spring data jdbc: one-to-one, one-to-many relations
Т.к. в Spring Data JDBC нет стандартных хибернейтовских аннотаций типа @OneToOne, @OneToMany и @JoinColumn, то для меня было проблематично понять можно ли там вообще организовать отношения и использовать их при получении или сохранении объектов. Оказалось это делается так: One-To-One При такой реализации объект Operation без проблем вычитывается из БД уже с смапленным внутрь TaxInfo. Так же без проблем работает сохранение нового Operation с заполненным TaxInfo (корректно заполняются поля id и operationId. One-To-Many Несколько проблематично отношение один ко многим. Здесь сложность состояла в том, что я использовал List для агрегации нескольких TaxInfo, и при сохранении получал эксепшн ConstraintViolationException. Решение состояло в том, чтобы использовать Set (или Map): При такой реализации объект Operation без проблем вычитывается из БД уже с смапленными внутрь TaxInfo. Так же без проблем работает сохранение нового Operation с заполненными TaxInfo (корректно заполняются поля id и operationId. Теперь про эксепшены. У меня были проблемы именно с аннотацией @MappedCollection в…
Задержка принятия следующего Jms сообщения после ошибки
Вариант реализации JmsListenerContainerFactory (на основе DefaultJmsListenerContainerFactory) для задержки принятия следующего jms сообщения, если был выброшен необработанный эксепшен: Инициализация выглядит следующим образом
9.Транзакционность в JMS
Транзакционность используется для возвращения сообщения обратно в очередь, в случае возникновения исключения при его обработке. Для настройки транзакционности, нужно указать ContainerFactory бину — бин PlatformTransactionManager. Пример настроек JMS: Для того, чтобы rollback сообщения сработал, достаточно чтобы из метода помеченного @JmsListener выбросилось необработанное исключение. Таким образом, исходное сообщение снова появится в очереди и его хэадер JMSXDeliveryCount увеличится на 1. Но здесь есть сайд-эффект, т.к. это сообщение через секунду снова залетит в приложение. Таким образом, если исключение будет постоянно появляться — мы попадём в бесконечный цикл ( есть способ задержки принятия следующего Jms сообщения после ошибки ). По поводу транзакционности, есть пара статуй от IBM: https://community.ibm.com/community/user/integration/blogs/stephanie-wilkerson1/2021/02/25/understanding-mq-backout-queues-thresholds https://www.ibm.com/docs/en/ibm-mq/9.2?topic=applications-handling-poison-messages-in-mq-classes-jms
Кастомная Jackson десериализация/сериализация
Допустим, имеем такую DTO: А нам нужно десериализовать из такого json: То используем над полем аннотацию @JsonDeserialize(using = ProductDtoDeserializer.class) и делаем десериализатор А теперь сделаем так, чтобы строковое поле сериализовывалось в UpperCase
Проверка json в mockMVC тестах и не только
Протестировать ваш jsonPath можно в сервисе https://jsonpath.com/ Кроме того, просто извлечь значение согласно указанного jsonPath можно так:
Добавление модулей в ObjectMapper
Часто бывают проблемы с десериализацией дат из строки в, например, LocalDateTime. Порой это выглядит так: Есть несколько способов решить эту проблему. Один из них е использование аннотации @JsonFormat над нужным полем в dto Но бывают случаи, когда такое решение не приемлемо. Однако, есть ещё способ — кастомизация самого ObjectMapper’а. Я имею в виду про добавление модулей для сериализации/десериализации. Например, добавление модуля поддержки jsr310: Или добавление модуля поддержки joda: Наряду с этим, есть возможность писать собственные модули для сериализации/десериализации чего угодно. Не отходя от темы дат, приведу пример десериализации даты, представленной в любом из ожидаемых форматов: где классы выглядят так:
Профилирование java приложений
Если приложение сжирает слишком много памяти, либо сильно грузит проц, то можно на скорую руку сделать его профилирование. Ниже представлены команды, которые, при запуске на сервере, могут дать понять — в чём проблема. Отображение потребления ресурсов потокам С помощью диспетчера процессов top, можно отобразить список потоков приложения: где 20345 — это PID запущенного процесса Вашего приложения Сэмплинг Помогает найти тормозные методы в приложении. Суть метода заключается в выполнении скоупа нескольких одинаковых запросов. Каждый запрос показывает методы, в которых в данный момент находятся потоки приложения. Таким образом, если в нескольких запросах фигурирует один и тот же метод, то можно предположить, что он является очень долгим и, возможно, требует оптимизации. Команда для выполнения одного запроса: где 20345 — это PID запущенного процесса Вашего приложения (можно узнать в диспетчере процессов top), ru.knastnt — корневое имя всех пакетов в моём приложении. Это нужно чтобы показывать только методы, написанные непосредственно мной. Потому что без grep,…