Skip to content

Releases: etsft/max-bot-api-java

Release 0.5.0

Choose a tag to compare

@batarelkin batarelkin released this 14 Sep 09:38

Релиз переводит библиотеку на Jackson 3 и Spring Boot 4.

В релизе есть изменения, ломающие совместимость как по исходному коду,
так и бинарно: модуль max-bot-api-jackson работает только с Jackson 3,
стартер — только со Spring Boot 4. Модели, MaxBotAPI и остальные модули
не изменились.

Координаты артефактов: ru.etsft.max:max-bot-api-*:0.5.0.

ЛОМАЮЩИЕ ИЗМЕНЕНИЯ

  • max-bot-api-jackson построен на Jackson 3 (tools.jackson.*, 3.1.5) и
    транзитивно подтягивает tools.jackson.core:jackson-databind вместо
    com.fasterxml.jackson.core. С Jackson 2 модуль не работает.
  • JacksonMaxSerializer.getObjectMapper() возвращает
    tools.jackson.databind.ObjectMapper. Собственные сериализаторы и
    десериализаторы, зарегистрированные в этом mapper-е, нужно перевести на
    API Jackson 3 (ValueSerializer, ValueDeserializer, SerializationContext).
    Аннотации остаются в com.fasterxml.jackson.annotation.
  • max-bot-api-spring-boot требует Spring Boot 4.x. Для webhook-режима
    вместо spring-boot-starter-web нужен spring-boot-starter-webmvc.

СОХРАНЁННОЕ ПОВЕДЕНИЕ

  • JSON на входе и выходе такой же, как в 0.4.1. Там, где у Jackson 3
    изменились значения по умолчанию, выставлено прежнее поведение:
    null-поля не сериализуются (NON_NULL), null для примитивов не вызывает
    ошибку (FAIL_ON_NULL_FOR_PRIMITIVES отключён).
  • Перечисления по-прежнему пишутся в нижнем регистре: Jackson 3 не
    спрашивает findSerializer для enum, поэтому сериализатор
    зарегистрирован через findEnumSerializer. Без этого значения ушли бы в
    MAX в верхнем регистре.

ЗАВИСИМОСТИ

  • Jackson 2.21.1 → 3.1.5, Spring Boot 3.5.12 → 4.1.1,
    SLF4J 2.0.17 → 2.0.19.
  • Только для сборки и тестов: JUnit 5.14.3 → 6.0.3, JsonUnit 4.1.1 → 6.2.0,
    WireMock 3.13.1 → 3.13.2, Checkstyle 10.20.1 → 14.1.0,
    плагин SpotBugs 6.4.8 → 6.5.11, Gradle 9.4.1 → 9.7.1 (wrapper и образы
    в CI).

СБОРКА И ВЫПУСК

  • Новая задача ./gradlew centralBundle: собирает подписанные артефакты
    всех публикуемых модулей в build/central-bundle/
    max-bot-api-java-<версия>-bundle.zip с раскладкой Maven в корне — архив,
    который раньше приходилось собирать вручную.
  • Подпись обязательна, если передан ключ (signing.keyId или
    signingInMemoryKey): ошибка в настройке ключа роняет сборку, а не даёт
    неподписанный бандл.
  • GitLab CI, job publish: запускается вручную на тегах строго вида
    vX.Y.Z; проверяет, что тег совпадает с version в gradle.properties;
    подписывает ключом из защищённых переменных; убеждается, что .asc на
    месте; загружает бандл через Central Publisher API
    (scripts/central-upload.sh) в режиме USER_MANAGED и ждёт валидации.
    Окончательная публикация подтверждается в Central Portal.

ДОКУМЕНТАЦИЯ

  • README и README_RU: Jackson 3.x, Spring Boot 4.x,
    spring-boot-starter-webmvc для webhook-режима, версия 0.5.0 в примерах
    подключения.

ПРОВЕРКА

  • ./gradlew clean build: 680 модульных тестов, Checkstyle, SpotBugs,
    пороги покрытия — без ошибок. Тесты Jackson и клиента проходят и на
    Jackson 3.1.5 из BOM Spring Boot 4.1.1.
  • ./gradlew centralBundle: бандл содержит 7 модулей с jar, sources,
    javadoc, pom, module, подписями и контрольными суммами. Сборка с
    некорректным ключом падает; загрузка с неверным токеном завершается
    ошибкой 401.
  • liveTest против боевого MAX API на Jackson 3: 52 теста, 48 успешно,
    0 падений. Сериализация и разбор ответов сервера через Jackson 3 проходят
    на реальных данных. 4 теста пропущены окружением: deleteChat — MAX
    отказывает боту (нужно владение чатом), webhookRoundTrip — не задан
    MAX_IT_WEBHOOK_URL, unsubscribe — зависит от него и пропускается, так
    как подписка не создавалась, getChatByLink — в MAX_IT_CHAT_LINK
    ссылка-приглашение.

Release 0.4.1

Choose a tag to compare

@batarelkin batarelkin released this 13 Sep 18:07

Релиз с исправлениями

Главное — клиент сам дожидается, пока MAX обработает загруженное вложение, поэтому отправка сообщения сразу после загрузки больше не падает с attachment.not.ready. Кроме того, исправлены откат long polling и примеры, README приведён в соответствие с кодом.

Изменений, ломающих совместимость по исходному коду или бинарно, нет.

Координаты артефактов: ru.etsft.max:max-bot-api-*:0.4.1.

ИЗМЕНЕНИЕ ПОВЕДЕНИЯ

  • sendMessage (и любой запрос, получивший attachment.not.ready) больше не выбрасывает AttachmentNotReadyException сразу: клиент повторяет тот же запрос до 30 секунд и блокирует вызывающий поток на это время. Прежнее поведение — MaxClientConfig.builder().attachmentReadyTimeout(Duration.ZERO).

НОВОЕ

  • MaxClientConfig.attachmentReadyTimeout (по умолчанию 30 секунд, DEFAULT_ATTACHMENT_READY_TIMEOUT) и одноимённый метод builder-а. Пока MAX отвечает attachment.not.ready, клиент повторяет неизменённый запрос с паузами 0,5 с, 1 с, 2 с, далее каждые 3 с; исключение выбрасывается только после таймаута. Повтор безопасен: отклонённое сообщение не создаётся, токен загрузки остаётся действительным. Работает и для enqueue(). Прежний 8-аргументный конструктор MaxClientConfig сохранён.
  • RetryPolicy.attachmentRetryDelay(int) — расписание этих пауз.
  • Примеры WebhookBot (MaxWebhookServer с секретом, dispatch executor, подписка при старте и отписка при остановке) и CommentsBot (отвечает на комментарии к постам, пропуская собственные).

ИСПРАВЛЕНИЯ

  • MaxLongPollingConsumer: откат после ошибок опроса останавливался на 16 секундах, хотя javadoc и README обещают 1 → 2 → 4 → 8 → 16 → 30 с. Теперь доходит до 30 секунд.
  • Примеры:
    • команда ./gradlew :max-bot-api-examples:run -PmainClass=... из их описаний не работала — в модуль добавлен плагин application (без -PmainClass запускается EchoBot);
    • KeyboardBot падал на callback без payload и не отвечал на него;
    • ImageUploadBot передавал токен endpoint-а вместе с photos, VideoUploadBot и AudioUploadBot брали токен не из результата загрузки; все три при запуске называли себя FileUploadBot;
    • FileUploadBot оставлял временный файл при ошибке загрузки;
    • MaxBotAPI теперь закрывается во всех примерах.
  • Плавающий тест MaxLongPollingConsumerTest.malformedUpdateInBatchStillAdvancesMarker: требовал третий опрос, который на загруженном CI не всегда успевал дойти до сервера до проверки.

ДОКУМЕНТАЦИЯ

  • README и README_RU:
    • ожидание attachment.not.ready и настройка attachmentReadyTimeout;
    • Webhooks: пример register() шёл до создания сервера; start() — это HTTP, для HTTPS — start(SSLContext); значения по умолчанию порта и пути; секрет передаётся в MAX при register();
    • Spring Boot: нужны max-bot-api-jackson и, для webhook, spring-boot-starter-web; собственный бин MaxBotAPI для настроек клиента;
    • Long polling: реальное расписание отката, ошибки обработчика отката не вызывают; pollTimeout;
    • в иерархию исключений добавлены MaxMethodNotAllowedException и AttachmentNotReadyException; закрытие MaxBotAPI и MaxUploadAPI; запуск и полный список примеров; ответ на комментарий;
    • ссылки, бейджи и правила участия ведут на GitHub, ветка master.
  • POM: SCM connection указывает на GitHub, а не на закрытый GitLab.

СБОРКА

  • Версии зависимостей и плагинов вынесены в Gradle Version Catalog (gradle/libs.versions.toml); разрешаемые версии не изменились.

ПРОВЕРКА

  • ./gradlew build: модульные тесты, Checkstyle, SpotBugs, пороги покрытия — без ошибок.
  • liveTest против боевого MAX API: 52 теста, 42 успешно, 0 падений. В логе видно, как MAX дважды ответил attachment.not.ready, а клиент повторил отправку через 500 мс и она прошла. 10 тестов пропущены окружением: разрушительные и интерактивные шаги отключены на время прогона, не задан MAX_IT_WEBHOOK_URL, в MAX_IT_CHAT_LINK ссылка-приглашение.
  • Все примеры с настоящим токеном запускаются и опрашивают API без ошибок; реакция на входящие сообщения вручную не проверялась.

Release 0.4.0

Choose a tag to compare

@batarelkin batarelkin released this 13 Sep 04:49

Релиз приводит библиотеку в соответствие с MAX Bot API: с OpenAPI-схемой
0.0.33, по которой построен сайт документации, и с тем, как на деле
отвечает боевой сервер. Добавлены комментарии к постам в каналах, новые
типы событий и живой интеграционный набор тестов.

В релизе есть изменения, ломающие совместимость как по исходному коду,
так и бинарно. Таблица замен — в разделе «Migrating to 0.4.0» README
(«Переход на 0.4.0» в README_RU).

Координаты артефактов: ru.etsft.max:max-bot-api-*:0.4.0.

ЛОМАЮЩИЕ ИЗМЕНЕНИЯ

  • Удалён GET /chats: MaxBotAPI.getChats(), GetChatsQuery и модель
    ChatList. MAX больше не поддерживает этот метод.
  • CommentRemovedUpdate: вместо объекта message событие содержит
    идентификаторы удалённого комментария: messageId, chatId, userId,
    postId. Раньше все четыре терялись.
  • OpenAppButton(text, webApp, contactId, payload): поле url удалено,
    webApp обязателен, contactId передаётся только вместе с ним. Добавлена
    фабрика ofWebApp(text, webApp). Схема допускает кнопку только с
    contact_id, но сервер её отклоняет («Field 'webApp' cannot be null»).
  • MessageButton(text): поле message удалено. Кнопка отправляет в чат
    собственный текст.
  • Message.body() может быть null: так приходит сообщение, которое только
    пересылает другое. Раньше такое сообщение не читалось, а внутри
    message_created превращало событие в UnknownUpdate.
  • ChatPatch.icon — PhotoAttachmentRequestPayload вместо Image: иконку чата
    можно задать внешним URL, токеном или загруженными photos.
  • lastActivityTime() в User, UserWithPhoto, BotInfo и ChatMember —
    Long вместо long: null, если время скрыто настройками приватности
    (раньше читался как 0).
  • VideoAttachmentDetails: поле url удалено, ссылки на варианты видео —
    в urls (новая модель VideoUrls: mp4_1080 … mp4_144, hls). Все поля,
    кроме token, nullable: пока видео обрабатывается, их может не быть.
  • ChatAdminsList содержит список ChatAdmin (userId, permissions, alias)
    вместо userIds — в формате, который принимает POST /chats/{id}/members/admins.
  • ContactAttachment.ContactPayload: tam_info заменён на maxInfo (max_info),
    добавлен hash для проверки HMAC-SHA256(access_token, vcf_info).
  • Новые компоненты record, меняющие их конструкторы:
    MarkupElement — url, userLink, userId (ссылки и упоминания);
    DialogClearedUpdate, DialogUnmutedUpdate, DialogRemovedUpdate,
    BotStoppedUpdate — userLocale; DialogMutedUpdate — mutedUntil и
    userLocale; MessageRemovedUpdate — postId; Subscription — time;
    AudioAttachment — transcription; ChatPatch — description;
    AddMembersResult — message; ChatMember — alias; MessageRecipient —
    postId и userId; UserWithPhoto — firstName и lastName.
  • name и firstName у пользователей теперь nullable: документация называет
    name устаревшим, но её собственный пример GET /me возвращает name без
    first_name.
  • MaxWebhookServer.register() и unregister() выбрасывают
    IllegalStateException, если MAX отвечает HTTP 200 с success=false.
    Раньше отказ игнорировался и в лог писалась успешная регистрация.

НОВОЕ

  • Комментарии к постам в каналах: getComments, getCommentById,
    sendComment, editComment, deleteComment и модели CommentMessage,
    CommentMessageBody, CommentLinkedMessage, NewCommentBody, CommentList,
    SendCommentResult.
  • Типы событий dialog_cleared, dialog_muted, dialog_unmuted,
    dialog_removed, comment_created, comment_edited, comment_removed —
    классы событий и значения UpdateType. Раньше на них нельзя было
    подписаться, а пришедшие события становились UnknownUpdate.
  • PATCH /me/commands — управление командами бота.
  • Кнопка clipboard (ClipboardButton).
  • Параметр disable_link_preview в POST /answers.
  • Webhook: асинхронная обработка по флагу —
    MaxWebhookServer.Builder.dispatchExecutor(...) и в Spring Boot
    max.bot.webhook.async-dispatch=true. Ответ 200 уходит сразу, обработчик
    выполняется после, поэтому долгая обработка не превышает 30 секунд,
    отведённых MAX на ответ. По умолчанию поведение прежнее.
  • ChatPermission снова распознаёт старые названия прав (edit_message,
    delete_message, post_edit_delete_message), которыми MAX всё ещё
    отвечает; canonical() сводит старое название к новому.
  • Живой интеграционный набор max-bot-api-integration-tests: вызывает
    методы MaxBotAPI с настоящим токеном и падает, если ответ не удаётся
    представить моделями. Запускается только вручную:
    ./gradlew :max-bot-api-integration-tests:liveTest.

ИСПРАВЛЕНИЯ

  • Одно некорректное событие больше не срывает разбор всего UpdateList.
    Раньше маркер long polling не продвигался, сервер повторял ту же
    пачку, и бот переставал получать события. Теперь неразборчивые
    события, вложения и кнопки превращаются в UnknownUpdate,
    UnknownAttachment и UnknownButton с исходным JSON, а
    MaxLongPollingConsumer предупреждает после трёх ошибок подряд.
  • Ошибка attachment.not.ready распознаётся: сервер отвечает HTTP 400 с
    кодом через точки, а не 409. Код ошибки теперь виден в сообщении
    MaxApiException.
  • getVideoAttachmentDetails больше не падает на реальных ответах сервера.
  • postAdmins отправляет тело, которое принимает API; раньше запрос всегда
    отклонялся.
  • getChatByLink принимает @name, name, max.ru/name и
    https://max.ru/name.
    Ссылку-приглашение отклоняет сразу, без запроса.
  • GET /subscriptions не падает с NullPointerException, если подписка
    содержит неизвестный библиотеке тип события.
  • Spring-регистратор webhook при success=false пишет в лог ошибку, а не
    сообщение об успешной регистрации.
  • Примеры не падают на постах канала без sender и на сообщениях без body.

УСТАРЕВШЕЕ (@deprecated, будет удалено)

  • POST /chats/{chatId}/members (AddMembersQuery): MAX ограничил метод с
    9 сентября 2026 года и удаляет его 30 сентября 2026 года.
  • Наследие TamTam, которого нет в документации MAX: PATCH /me
    (EditMyInfoQuery, замена — PATCH /me/commands), DELETE /chats/{chatId}
    (боту отказано: нужно владение чатом), GET /chats/{chatLink}, параметр
    user_id в GET /messages, кнопка chat, SenderAction.MARK_SEEN,
    ChatStatus.SUSPENDED, события message_construction_request,
    message_constructed и message_chat_created вместе с их UpdateType,
    Message.constructor.

ДОКУМЕНТАЦИЯ

  • README и README_RU: работа с комментариями и командами бота, таблица
    всех типов событий, срок ответа webhook (30 секунд), политика повторов
    и async-dispatch, лимит MAX в 2 операции в секунду на один чат, раздел
    о переходе на 0.4.0. Исправлен пример MaxWebhookServer, который
    вызывал несуществующий метод api(...).

ПРОВЕРКА

  • ./gradlew build: модульные тесты, Checkstyle, SpotBugs — без ошибок.
  • liveTest против боевого MAX API: 52 теста, 0 падений. Пропуски
    вызваны окружением: webhookRoundTrip — не задан MAX_IT_WEBHOOK_URL
    (в предыдущем прогоне этого дня проходил), deleteChat — MAX отказывает
    боту, getChatByLink — в конфигурации ссылка-приглашение.

Release 0.3.2

Choose a tag to compare

@batarelkin batarelkin released this 17 Jul 14:19

Bundle MAX-required Russian trusted CA certificates into the client resources and use them in the default SSLContext together with the JVM trust store

Release 0.3.1

Choose a tag to compare

@batarelkin batarelkin released this 28 Apr 05:38

Исправлена ошибка с некорректным возвращаемым значением при загрузке изображений, видео и аудио.

MaxUploadAPI теперь содержит три метода для загрузки различных вложений:

  • uploadFile (загрузка файлов)
  • uploadImage (закгрузка изображений)
  • uploadMedia (закгрузка видео и аудио)

Release 0.3.0

Release 0.3.0 Pre-release
Pre-release

Choose a tag to compare

@batarelkin batarelkin released this 13 Apr 04:10
  1. Added PollingErrorHandler support to MaxLongPollingAutoConfiguration
  2. Introduced UpdateType enum in max-bot-api-core covering all 14 known update types. All string-based update type APIs replaced with typed ones
  3. Added MaxBotMode.NONE to explicitly disable bot update delivery

Release 0.2.0

Release 0.2.0 Pre-release
Pre-release

Choose a tag to compare

@batarelkin batarelkin released this 30 Mar 05:25

MAX Bot API Java Client — v0.2.0

Group ID: ru.etsft.max
Java: 21+
License: Apache 2.0


Breaking Changes

Unified UpdateHandler interface

WebhookHandler and MaxLongPollingConsumer.UpdateHandler have been replaced by a single shared interface in the core module:

ru.max.botapi.core.UpdateHandler

Both webhook and long-polling modes now use this interface. Define one handler bean and switch between modes by changing only the max.bot.mode property — no code changes required.

Migration:

Before (0.1.0) After (0.2.0)
WebhookHandler UpdateHandler
MaxLongPollingConsumer.UpdateHandler UpdateHandler
handler.onError(e) (default method) .onError(e -> ...) on builder

onError moved to builder

The onError default method was removed from the handler interface and moved to MaxLongPollingConsumer.Builder.onError(Consumer<Exception>). If not set, errors are logged at WARN level (same default behavior as before).

// Before
MaxLongPollingConsumer.builder()
    .handler(new MaxLongPollingConsumer.UpdateHandler() {
        public void onUpdate(Update update) { ... }
        public void onError(Exception e) { ... }
    })
    .build();

// After
MaxLongPollingConsumer.builder()
    .handler(update -> { ... })
    .onError(e -> { ... })
    .build();

New Features

Auto-created MaxSerializer for webhook mode

The webhook auto-configuration now automatically extracts the MaxSerializer from the MaxBotAPI bean. Users no longer need to declare a MaxSerializer bean manually — it just works when a token is configured.

Previously, missing the MaxSerializer bean caused the webhook controller to silently not start.

serializer() accessor on MaxBotAPI and MaxClient

MaxBotAPI api = MaxBotAPI.create("token");
MaxSerializer serializer = api.serializer();

Publishing guide

Added PUBLISHING.md with step-by-step instructions for publishing to Maven Central via the Central Portal: account setup, GPG key generation, local staging, bundle upload, and CI/CD integration.


Installation

Gradle (String Boot)

dependencies {
    implementation("ru.etsft.max:max-bot-api-spring-boot:0.2.0")
    implementation("ru.etsft.max:max-bot-api-jackson:0.2.0")
}

Maven (String Boot)

<dependency>
    <groupId>ru.etsft.max</groupId>
    <artifactId>max-bot-api-spring-boot</artifactId>
    <version>0.2.0</version>
</dependency>
<dependency>
    <groupId>ru.etsft.max</groupId>
    <artifactId>max-bot-api-jackson</artifactId>
    <version>0.2.0</version>
</dependency>

Gradle

dependencies {
    implementation("ru.etsft.max:max-bot-api-client:0.2.0")
    implementation("ru.etsft.max:max-bot-api-jackson:0.2.0")
    implementation("ru.etsft.max:max-bot-api-longpolling:0.2.0")
}

Maven

<dependency>
    <groupId>ru.etsft.max</groupId>
    <artifactId>max-bot-api-client</artifactId>
    <version>0.2.0</version>
</dependency>
<dependency>
    <groupId>ru.etsft.max</groupId>
    <artifactId>max-bot-api-jackson</artifactId>
    <version>0.2.0</version>
</dependency>
<dependency>
    <groupId>ru.etsft.max</groupId>
    <artifactId>max-bot-api-longpolling</artifactId>
    <version>0.2.0</version>
</dependency>

Spring Boot Quick Start

max:
  bot:
    mode: longpolling   # or "webhook"
    longpolling:
      token: "your-bot-token"
@Bean
UpdateHandler updateHandler() {
    return update -> System.out.println("Got: " + update.updateType());
}

Same handler works for both modes.

Basic configuration for longpolling/webhook:

max:
  bot:
    mode: longpolling # or webhook
    webhook:
      url: "https://<your base url>/api/webhook"
      path: "/api/webhook"
      secret: "some random secret here"
      token: "your-bot-token"
    longpolling:
      token: "your-bot-token"

Links

Release 0.1.0

Release 0.1.0 Pre-release
Pre-release

Choose a tag to compare

@batarelkin batarelkin released this 27 Mar 09:14

MAX Bot API Java Client — v0.1.0

Initial release of the Java 21 client library for the MAX Messenger Bot API.

Group ID: ru.etsft.max
Java: 21+
License: Apache 2.0


Modules

Module Artifact ID Description
Core max-bot-api-core Models, sealed interfaces, enums — zero external dependencies
Client max-bot-api-client HTTP transport via java.net.http.HttpClient, query builders, rate limiter
Jackson max-bot-api-jackson Jackson serialization adapter with custom polymorphic deserializers
Gson max-bot-api-gson Gson serialization adapter (placeholder)
Webhook max-bot-api-webhook Webhook HTTPS server for receiving updates
Long Polling max-bot-api-longpolling Long polling consumer with virtual threads
Spring Boot max-bot-api-spring-boot Spring Boot auto-configuration for webhook and long polling
Test Support max-bot-api-test-support WireMock stubs and JSON fixtures for testing
Examples max-bot-api-examples Echo bot, keyboard bot, file upload bot (not published)

Installation

Gradle

dependencies {
    implementation("ru.etsft.max:max-bot-api-client:0.1.0")
    implementation("ru.etsft.max:max-bot-api-jackson:0.1.0")
    implementation("ru.etsft.max:max-bot-api-longpolling:0.1.0")

    // Optional: Spring Boot auto-configuration
    // implementation("ru.etsft.max:max-bot-api-spring-boot:0.1.0")
}

Maven

<dependency>
    <groupId>ru.etsft.max</groupId>
    <artifactId>max-bot-api-client</artifactId>
    <version>0.1.0</version>
</dependency>

Highlights

Java 21 Idiomatic Design

  • 83 record types for all DTOs — fully immutable, no getters/setters
  • 4 sealed interface hierarchies with exhaustive pattern matching:
    • Attachment (9 types + UnknownAttachment)
    • AttachmentRequest (9 types + UnknownAttachmentRequest)
    • Button (7 types + UnknownButton)
    • Update (14 types + UnknownUpdate)
  • 8 enums for API constants (chat type, chat status, sender action, etc.)
  • Virtual threads for HTTP transport and long polling

Full API Coverage

All 31 API methods implemented as type-safe query builders:

Category Methods
Bot getMyInfo, editMyInfo
Chats getChats, getChat, getChatByLink, editChat, deleteChat, sendAction
Members getMembers, addMembers, removeMember, getMembership, leaveChat
Admins getAdmins, postAdmins, deleteAdmins
Messages getMessages, getMessageById, sendMessage, editMessage, deleteMessage
Pins getPinnedMessage, pinMessage, unpinMessage
Callbacks answerOnCallback
Subscriptions getSubscriptions, subscribe, unsubscribe
Updates getUpdates
Uploads getUploadUrl
Video getVideoAttachmentDetails

Update Delivery

  • Long Polling — runs on virtual threads with configurable poll timeout, automatic marker tracking, exponential backoff on errors, graceful shutdown
  • Webhook Server — built-in HTTPS server with secret header validation, configurable port, automatic update deserialization
  • Spring Boot Auto-Configuration — single max.bot.mode property selects between webhook and longpolling; includes lifecycle management, auto-registration, and health monitoring

Serialization

  • Jackson adapter — custom StdDeserializer implementations for all polymorphic hierarchies; zero Jackson annotations in core models
  • snake_case ↔ camelCase property naming handled transparently
  • Forward-compatible — unknown update types, attachment types, button types, and extra JSON fields are tolerated without exceptions

Error Handling

  • Structured exception hierarchy: MaxApiException, MaxClientException, MaxRateLimitException, MaxMethodNotAllowedException, AttachmentNotReadyException
  • Automatic retry on 429 (rate limit) and 503 (service unavailable) with exponential backoff
  • Token-bucket rate limiter (30 rps) applied before every request
  • Configurable timeouts for connection and request

Spring Boot Integration

max:
  bot:
    mode: longpolling       # or "webhook"
    longpolling:
      token: "your-bot-token"
      poll-timeout: 30
  • max.bot.mode enum property — mutually exclusive mode selection
  • Startup warning when mode is not configured
  • Auto-creates MaxBotAPI bean from token
  • Lifecycle-managed consumer/webhook with Spring context start/stop
  • Auto-registers/unregisters webhook subscription on startup/shutdown

Quality

  • 549 tests (unit, serialization round-trip, WireMock integration)
  • JaCoCo coverage gates: ≥85% line, ≥80% branch
  • Checkstyle enforced: 120-char lines, no wildcard imports
  • SpotBugs static analysis on all production code
  • Javadoc on all public API classes and methods
  • Apache 2.0 license headers on all source files

Requirements

  • Java 21 or later
  • Jackson 2.21+ (if using max-bot-api-jackson)
  • Spring Boot 3.5+ (if using max-bot-api-spring-boot)

Links