Spring Boot makes it easy to create stand-alone, production-grade Spring based Applications that you can “just run”.
Example
Here is an example project that shows how to use Spring with JAICF and MongoDB. Please investigate this example to learn how to develop, configure, build and run JAICF projects in production using Spring and Docker.
How to use
1. Append Spring Boot dependencies to build.gradle
plugins {
kotlin("jvm") version "1.4.21"
kotlin("plugin.spring") version "1.4.21"
id("org.springframework.boot") version "2.4.4"
id("io.spring.dependency-management") version "1.0.8.RELEASE"
}
dependencies {
implementation(kotlin("stdlib"))
implementation("org.springframework.boot:spring-boot-starter-web")
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
...
}
tasks {
compileKotlin {
kotlinOptions.jvmTarget = "1.8"
}
compileTestKotlin {
kotlinOptions.jvmTarget = "1.8"
}
bootJar {
archiveFileName.set("app.jar")
mainClass.set("com.justai.jaicf.spring.ApplicationKt")
}
}
tasks.create("stage") {
dependsOn("bootJar")
}
2. Configure BotEngine
With Spring you can write your scenarios as components to achieve all features of Spring like dependency injection and others.
@Component
class MainScenario(
private val botConfiguration: BotConfiguration
): Scenario {
override val model = createModel {
...
}
}
And then configure BotEngine
via Spring configuration
@Configuration
class ApplicationConfiguration(
private val botConfiguration: BotConfiguration
) {
@Bean
fun botApi(mainScenario: MainScenario) = BotEngine(
scenario = mainScenario,
activators = arrayOf(RegexActivator),
conversationLoggers = arrayOf(
JaicpConversationLogger(botConfiguration.accessToken),
Slf4jConversationLogger()
)
)
@Bean
fun jaicpWebhookConnector(botApi: BotApi) = JaicpWebhookConnector(
botApi = botApi,
accessToken = botConfiguration.accessToken,
channels = listOf(ChatWidgetChannel)
)
}
3. Run BotEngine
Create poller for development:
@Component
@Profile("dev")
class Poller(
private val botApi: BotApi,
private val botConfiguration: BotConfiguration
): ApplicationRunner, CoroutineScope {
override val coroutineContext = Dispatchers.Default
override fun run(args: ApplicationArguments?) {
launch {
JaicpPollingConnector(
botApi = botApi,
accessToken = botConfiguration.accessToken,
channels = listOf(ChatWidgetChannel)
).runBlocking()
}
}
}
Or webhook endpoint for production:
@RestController
class WebhookEndpoint(private val jaicpWebhookConnector: JaicpWebhookConnector) {
@PostMapping("/webhook")
fun processRequest(@RequestBody request: String) =
jaicpWebhookConnector.process(request.asHttpBotRequest()).let { response ->
ResponseEntity
.status(response.statusCode)
.headers { it.setAll(response.headers) }
.body(response.output.toString())
}
}
You may also use HttpBotChannelServlet instead:
@Configuration
@ServletComponentScan
class Context {
@WebServlet("/")
class AlexaController: HttpBotChannelServlet(
AlexaChannel(helloWorldBot)
)
}