I'm trying to create Micronaut bean with @RequestScope, but with each injection, there is a new instance created. I would expect it to create new instance only once per request.
Here is an example code:
@RequestScope
class RequestContext {
var foo: String? = null
}
@Controller("/example")
class ExampleController(
val requestContext: RequestContext,
val exampleService: ExampleService
) {
@Get()
fun example() {
requestContext.foo = "foo"
exampleService.example()
}
}
@Singleton
class ExampleService(
val requestContext: RequestContext
) {
fun example() {
println(requestContext.foo) // prints nul instead of "foo"
}
}
I have also tried wrapping RequestContext in Provider like here: micronaut @RequestScope - not creating bean per incoming http-request but it changes nothing.
What am doing wrong? How can I properly inject RequesScope bean into Singleton?
Micronaut Version: 4.5.1 Kotlin Version: 1.9.23
I could reproduce the behavior you describe.
I made your code work by following the pattern with getter/setter from this guide: Micronaut Scope Types
New version of class RequestContext
with getter/setter:
import io.micronaut.runtime.http.scope.RequestScope
@RequestScope
class RequestContext {
private var foo: String? = null
fun getFoo(): String? = foo
fun setFoo(foo: String) {
this.foo = foo
}
}
ExampleService:
import jakarta.inject.Singleton
@Singleton
class ExampleService(
private val requestContext: RequestContext
) {
fun example() {
println(requestContext.getFoo()) // will now print "foo"
}
}
ExampleController:
import io.micronaut.http.annotation.Controller
import io.micronaut.http.annotation.Get
@Controller("/example")
class ExampleController(
private val requestContext: RequestContext,
private val exampleService: ExampleService
) {
@Get
fun example() {
requestContext.setFoo("foo")
exampleService.example()
}
}
An interesting observation (not part of the question) is that with a class like this:
import io.micronaut.http.HttpRequest
import io.micronaut.runtime.http.scope.RequestAware
import io.micronaut.runtime.http.scope.RequestScope
@RequestScope
class RequestContext : RequestAware {
var foo: String? = null
override fun setRequest(request: HttpRequest<*>?) {
this.foo = "bar"
}
}
code compiles, but setRequest
is never called.
Making foo
private with getter getFoo
, setRequest
will be invoked.
import io.micronaut.http.HttpRequest
import io.micronaut.runtime.http.scope.RequestAware
import io.micronaut.runtime.http.scope.RequestScope
@RequestScope
class RequestContext : RequestAware {
private var foo: String? = null
override fun setRequest(request: HttpRequest<*>?) {
this.foo = "bar"
}
fun getFoo(): String? = this.foo
}