Migrating from 0.0.6 to 0.0.7
Overview
Version 0.0.7 contains no breaking changes. All additions are either:
- Additive — new features, new properties with safe defaults
- Fail-fast for existing misconfigurations — errors that previously caused silent misbehaviour
now throw
BeanCreationExceptionat startup so they are caught before production
Upgrade is a single version bump for most projects:
<dependency>
<groupId>uz.osoncode.easygram</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>0.0.7</version>
</dependency>
What might affect your application
1. Duplicate handler methods — startup failure
If your project has two @BotController methods with the same routing condition (same annotation
- same value + same effective
@BotChatState), the application will now fail to start.
How to find them: Look for BeanCreationException in your startup logs with the message
Duplicate handler mapping detected. The message names both conflicting methods.
What to do:
- If the duplication is accidental — remove or rename one method.
- If you intended two handlers for the same condition with priority — add distinct
@BotOrdervalues (this is valid and no longer triggers the error).
// ✅ Valid — different @BotOrder values, same condition
@BotCommand("/admin")
@BotOrder(1)
public String onAdminSuperUser() { ... }
@BotCommand("/admin")
@BotOrder(100)
public String onAdminFallback() { ... }
2. Webhook requireSecretToken — startup failure on misconfiguration
Only affects you if you set require-secret-token: true in your webhook configuration.
If require-secret-token: true is set but secret-token is absent or blank, the application
now fails at startup. Previously this combination was silently accepted.
Fix: Either provide the secret-token property, or remove require-secret-token: true:
easygram:
update:
webhook:
require-secret-token: true
secret-token: ${WEBHOOK_SECRET} # ← must be present and non-blank
3. Blank @BotMarkup / @BotReplyMarkup / @BotForwardChatState — startup failure
If any handler method has a blank string value for these annotations, the application now fails at startup.
Examples that now fail:
@BotMarkup("") // ← BeanCreationException
@BotReplyMarkup("") // ← BeanCreationException
@BotForwardChatState("") // ← BeanCreationException
Fix by providing the correct non-blank value (the markup identifier or state name).
4. Error counter — new exception tag (dashboard action needed)
The easygram.update.error_total counter now has an exception dimension containing the
simple class name of the exception.
Impact: If you have Grafana dashboards, Prometheus alerting rules, or Datadog monitors
querying easygram_update_error_total without a label selector, they continue to work
(summing across all exception types).
If you have queries that expect the counter to have no labels, add a wildcard matcher:
# Before (still works — sums all exception types)
rate(easygram_update_error_total[1m])
# Recommended — be explicit about aggregation
sum(rate(easygram_update_error_total[1m])) by (exception)
# Filter to a specific type
rate(easygram_update_error_total{exception="TelegramApiException"}[1m])
5. Telegram send error classification — 4xx suppressed, 5xx propagated
BotApiMethodsSenderFilter now distinguishes between retryable and non-retryable Telegram
API errors:
- 4xx (client errors) — logged as
ERRORand suppressed (not re-thrown). These are permanent failures: resending the same message payload will never succeed. Suppressing prevents broker transports (RabbitMQ consumer) from entering an infinite requeue loop. Fix the message content in your handler. - 5xx / network errors — logged as
ERRORand re-thrown so that your@BotExceptionHandlermethods can handle them (retry, alert, etc.).
If your bot has a broad Telegram error handler: Handlers that previously caught all
TelegramApiException instances will now only fire for 5xx / network errors. 4xx errors
are suppressed before reaching any handler.
// Receives only 5xx and network errors — 4xx are suppressed at the sender filter
@BotExceptionHandler(TelegramApiException.class)
public void onTelegramError(TelegramApiException e) {
log.error("Transient Telegram API error: {}", e.getMessage());
}
6. Duplicate @BotExceptionHandler detection — startup failure
If your project has two methods inside @BotController beans (or two inside
@BotControllerAdvice beans) that declare @BotExceptionHandler for the same exception
type and the same effective @BotChatState, the application now fails to start.
How to find them: Look for BeanCreationException with Duplicate @BotExceptionHandler mapping detected in your startup logs. The message names both conflicting methods.
What to do:
- Remove or rename one of the conflicting exception handler methods.
- If you need different behavior per state — add distinct
@BotChatStateto each method. - A
@BotControllerand a@BotControllerAdvicehandler for the same exception type are in separate priority groups and are not flagged as duplicates.
7. RabbitMQ consumer: ACK-always policy
If you use the RABBIT_CONSUMER transport, RabbitBotUpdateListener now always ACKs AMQP
messages — regardless of whether processing succeeded or failed. Previously, an exception
was re-thrown, causing the AMQP container to NACK and requeue the message indefinitely.
Impact: Failed messages are no longer automatically retried via requeue. If you relied on the requeue behavior for retry logic, configure a Dead-Letter Exchange (DLX) on the broker to route failed messages to a separate queue for inspection and replay.
New features (additive, no migration required)
| Feature | How to use |
|---|---|
| Body size limit | Set easygram.update.webhook.max-body-bytes: <bytes> — default is unlimited |
@BotStartTrigger lambda | Use as a lambda in @Bean methods |
| Regex cache tuning | Up to 512 @BotTextPattern regexes are cached — no configuration needed |
Full changelog
See What's New in 0.0.7 for the complete feature summary.