Migrating from 0.0.1 to 0.0.2
Overview
Version 0.0.2 extends Easygram with handler annotations for every remaining Telegram Update
field, adds four new argument-injector annotations, exposes ten new type-based parameter
resolvers, and introduces clearState(chatId) as the explicit API for removing chat state.
Two breaking changes require minimal code edits — see the sections below.
Breaking Changes
1. setState(chatId, null) now throws IllegalArgumentException
What changed: In 0.0.1, passing null as the state to BotChatStateService.setState was
the only way to programmatically remove a chat state. This overload now throws
IllegalArgumentException since 0.0.2 to make intent explicit and prevent accidental state
loss.
Before (0.0.1):
chatStateService.setState(chat.getId(), null); // cleared the state
After (0.0.2):
chatStateService.clearState(chat.getId()); // use the dedicated clear method
Who is affected: Any code that calls setState with a literal null or a variable that
can be null. The @BotClearChatState annotation is unaffected — it internally calls
clearState and works as before.
2. PlainTextTemplate token format changed from {0} to #{0}
What changed: The positional token syntax for PlainTextTemplate changed from {0} to
#{0} (hash-prefixed) to avoid conflicts with other template systems and to align with the
LocalizedTemplate syntax.
Before (0.0.1):
PlainTextTemplate.of("Hello, {0}! You have {1} messages.", user.getFirstName(), count)
After (0.0.2):
PlainTextTemplate.of("Hello, #{0}! You have #{1} messages.", user.getFirstName(), count)
Who is affected: Every PlainTextTemplate template string that contains {N} tokens. A
global search for PlainTextTemplate.of (or .builder()) and replacing { → #{ inside
template strings will cover all cases. Be careful not to alter unrelated curly braces in your
strings.
3. Messaging transport broker dependencies now require explicit declaration
What changed: In 0.0.1, spring-boot-starter-amqp and spring-kafka were transitive
dependencies of the messaging consumer modules. This caused Spring Boot's RabbitAutoConfiguration
/ KafkaAutoConfiguration to activate on every startup, with RabbitAdmin attempting to
connect to localhost:5672 even when the bot used LONG_POLLING transport.
In 0.0.2 these broker dependencies are marked <optional>true</optional>. They are no longer
transitively inherited — you must add them explicitly when using the corresponding transport.
Who is affected: Users with transport: RABBIT_CONSUMER or transport: KAFKA_CONSUMER.
Before (0.0.1) — no extra dep needed:
<dependency>
<groupId>uz.osoncode.easygram</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>0.0.1</version>
</dependency>
<!-- spring-boot-starter-amqp / spring-kafka were pulled in automatically -->
After (0.0.2) — add the broker dep explicitly:
<dependency>
<groupId>uz.osoncode.easygram</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>0.0.2</version>
</dependency>
<!-- Add if using transport: RABBIT_CONSUMER -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
<!-- Add if using transport: KAFKA_CONSUMER -->
<dependency>
<groupId>org.springframework.kafka</groupId>
<artifactId>spring-kafka</artifactId>
</dependency>
Users on LONG_POLLING or WEBHOOK transport are unaffected and see the benefit of no
unwanted broker connection attempts at startup.
New Features
17 new handler annotations for all Telegram Update types
Easygram 0.0.2 ships a complete set of handler annotations covering every Update field that
was previously unroutable. All annotations live in
uz.osoncode.easygram.core.bind.annotation and follow the same rules as the existing ones.
| Annotation | Update getter | Docs |
|---|---|---|
@BotEditedMessage | getEditedMessage() | handlers |
@BotChannelPost | getChannelPost() | handlers |
@BotEditedChannelPost | getEditedChannelPost() | handlers |
@BotInlineQuery | getInlineQuery() | handlers |
@BotChosenInlineResult | getChosenInlineQuery() | handlers |
@BotShippingQuery | getShippingQuery() | handlers |
@BotPreCheckoutQuery | getPreCheckoutQuery() | handlers |
@BotPoll | getPoll() | handlers |
@BotPollAnswer | getPollAnswer() | handlers |
@BotMyChatMember | getMyChatMember() | handlers |
@BotChatMemberUpdate | getChatMember() | handlers |
@BotChatJoinRequest | getChatJoinRequest() | handlers |
@BotBusinessConnection | getBusinessConnection() | handlers |
@BotBusinessMessage | getBusinessMessage() | handlers |
@BotEditedBusinessMessage | getEditedBuinessMessage() | handlers |
@BotDeletedBusinessMessages | getDeletedBusinessMessages() | handlers |
@BotPaidMediaPurchased | getPaidMediaPurchased() | handlers |
No migration action is needed — these are purely additive.
4 new argument-injector annotations
| Annotation | Injects | Available in |
|---|---|---|
@BotInlineQueryValue | String — inline query text | @BotInlineQuery handlers |
@BotChosenInlineResultId | String — chosen result ID | @BotChosenInlineResult handlers |
@BotShippingPayload | String — invoice payload | @BotShippingQuery handlers |
@BotPreCheckoutPayload | String — invoice payload | @BotPreCheckoutQuery handlers |
10 new type-based argument resolvers
The following types are now injectable directly into handler method parameters when the handler is annotated with the corresponding annotation:
| Type | Handler annotation |
|---|---|
InlineQuery | @BotInlineQuery |
ChosenInlineResult | @BotChosenInlineResult |
ShippingQuery | @BotShippingQuery |
PreCheckoutQuery | @BotPreCheckoutQuery |
Poll | @BotPoll |
PollAnswer | @BotPollAnswer |
ChatMemberUpdated | @BotMyChatMember / @BotChatMemberUpdate |
ChatJoinRequest | @BotChatJoinRequest |
BusinessConnection | @BotBusinessConnection |
BusinessMessagesDeleted | @BotDeletedBusinessMessages |
See Parameter Injection — New Parameter Types (0.0.2) for full examples.
clearState(chatId) — explicit state clearing API
BotChatStateService now exposes clearState(Long chatId) as a dedicated method for removing
a chat's state. Replace any setState(chatId, null) call with clearState(chatId).
// Before
chatStateService.setState(chat.getId(), null);
// After
chatStateService.clearState(chat.getId());
If you have a custom BotChatStateService implementation, add the clearState method. The
default InMemoryBotChatStateService implementation is already updated.
core-observability now included in spring-boot-starter
spring-boot-starter now includes core-observability automatically. Users who add
spring-boot-starter-actuator and micrometer-registry-prometheus get the full observability
stack without any extra Easygram dependency.
What you get for free:
BotObservabilityFilter— wraps every update in aeasygram.updateMicrometer timerBotHealthIndicator— reports bot health (UP/UNKNOWN) at/actuator/healthBotInfoContributor— exposes bot metadata at/actuator/info
<!-- Add to enable Prometheus + health endpoints -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-prometheus</artifactId>
</dependency>
management:
endpoints:
web:
exposure:
include: health, info, prometheus
metrics:
distribution:
percentiles-histogram:
easygram.update: true
See Observability for the full guide.
Grafana dashboard in samples/i18n-registration-bot
The i18n-registration-bot sample now ships a complete observability stack:
samples/i18n-registration-bot/
├── docker-compose.yml # bot + Prometheus + Grafana
├── prometheus.yml # scrape /actuator/prometheus every 15 s
└── grafana/
├── provisioning/ # auto-provision datasource + dashboard directory
└── dashboards/
└── easygram-bot.json # 8-panel dashboard (throughput, latency, errors, health)
cd samples/i18n-registration-bot
TELEGRAM_BOT_TOKEN=xxx docker compose up
# Grafana → http://localhost:3000 (admin / admin)
Autoconfig Ordering Fix (informational)
The core-i18n module contained a bean ordering issue where BotReplyButtonMatcher could be
registered before the BotMessageSource it depends on was fully initialized. This is fixed in
0.0.2 via explicit @DependsOn ordering.
No user action is needed unless you had worked around this by manually ordering beans or
defining your own BotReplyButtonMatcher bean. If you did, you can safely remove the
workaround after upgrading.