Working with services
Services are certainly what contribute the most in making Botrino a so concise and easy to use framework. You will hopefully understand why after reading this page introducing services and showing how to use their power to their fullest extent.
#
What is a service?Services are more or less the same thing as beans in Spring. They are Java objects that are instantiated once at the start of your application, and that you can inject everywhere in your app. A service can define dependencies to other services, which are resolved when the service is created.
As such, the concept of dependency injection (DI) is also used in Botrino. Under the hood, it utilizes the RDI library which supports factories returning reactive types.
#
How to use services?Botrino will be able to find your services automatically in your app module, as long as your module is open
and is annotated with @BotModule
, as explained in the Getting Started guide.
#
Declaring a serviceFor a class to be recognized as a service, you need to annotate it with @RdiService
:
With only this code, an instance of A
will be created on startup. By default it assumes that a public no-arg constructor exists, which is the case in the code above. But there are many ways to construct a service, and that's what makes them interesting.
#
Injecting a service in a constructorLet's create another service B
, which injects A
in its constructor:
The @RdiFactory
annotation is what indicates the method to create the service, with the possibility to inject other services in the arguments. In this scenario, the following will happen on startup:
- Botrino will find
A
andB
in your module, and register them as services - It will see that
B
injectsA
in constructor, soA
needs to be created first beforeB
can be created - Services are created following the dependency tree.
#
Injecting a service in a static factoryThe method annotated with @RdiFactory
can as well be a static factory method instead of a constructor:
caution
The return type of the static factory must be B
or a subtype of B
.
#
Injecting a service in a reactive static factoryIf you need to perform some reactive tasks in order to create your object, Botrino (in fact, RDI) allows you to return a Publisher
of the service instead of the service itself:
In this case, if B
is injected somewhere else, it will first subscribe to the publisher returned by the static factory, and create the service only after the instance of B
is emitted.
info
Check out the RDI documentation for more examples and details on how dependency injection works.
#
Built-in servicesGatewayDiscordClient
#
Maybe you've been wondering how to access the instance of the Discord client of your bot? Well, now you have the answer: GatewayDiscordClient
is registered as a service, which means you can inject it in your own services!
ConfigContainer
#
To access the values of the configuration file, the service ConfigContainer
is registered and you can inject it in your own services. For example, to get the bot token:
We will see the ConfigContainer
more in depth in the next section, Configuring your bot.