Skip to main content
Version: 0.0.2

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.

AnnotationUpdate getterDocs
@BotEditedMessagegetEditedMessage()handlers
@BotChannelPostgetChannelPost()handlers
@BotEditedChannelPostgetEditedChannelPost()handlers
@BotInlineQuerygetInlineQuery()handlers
@BotChosenInlineResultgetChosenInlineQuery()handlers
@BotShippingQuerygetShippingQuery()handlers
@BotPreCheckoutQuerygetPreCheckoutQuery()handlers
@BotPollgetPoll()handlers
@BotPollAnswergetPollAnswer()handlers
@BotMyChatMembergetMyChatMember()handlers
@BotChatMembergetChatMember()handlers
@BotChatJoinRequestgetChatJoinRequest()handlers
@BotBusinessConnectiongetBusinessConnection()handlers
@BotBusinessMessagegetBusinessMessage()handlers
@BotEditedBusinessMessagegetEditedBuinessMessage()handlers
@BotDeletedBusinessMessagesgetDeletedBusinessMessages()handlers
@BotPaidMediaPurchasedgetPaidMediaPurchased()handlers

No migration action is needed — these are purely additive.


4 new argument-injector annotations

AnnotationInjectsAvailable in
@BotInlineQueryValueString — inline query text@BotInlineQuery handlers
@BotChosenInlineResultIdString — chosen result ID@BotChosenInlineResult handlers
@BotShippingPayloadString — invoice payload@BotShippingQuery handlers
@BotPreCheckoutPayloadString — 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:

TypeHandler annotation
InlineQuery@BotInlineQuery
ChosenInlineResult@BotChosenInlineResult
ShippingQuery@BotShippingQuery
PreCheckoutQuery@BotPreCheckoutQuery
Poll@BotPoll
PollAnswer@BotPollAnswer
ChatMemberUpdated@BotMyChatMember / @BotChatMember
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 a easygram.update Micrometer timer
  • BotHealthIndicator — reports bot health (UP/UNKNOWN) at /actuator/health
  • BotInfoContributor — 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.