I have a class the following class as RequestScope bean:
@RequestScope class RequestContext { private String requestId; private String traceId; private String authorisedId; private String routeName; // few more fields @Inject RequestContext(SecurityContext securityContext) { this.requestId = UUID.randomUUID().toString(); if(securityService.getAuthentication().isPresent()){ this.authorisedId = (securityService .getAuthentication().get()).getUserId().toString(); } } /* to be updated in controller method interceptors */ public void updateRouteName(String name){ this.routeName = name; }
The idea is to have an object containing the REST request level custom data accessible across the application, the scope of the this obviously should be within the current request. This can be used for say.. logging – whenever devs log anything from the application, some of the request meta data goes with it.
I am not clear what the @RequestScope bean really is:
From its definition – my assumption is it is created for every new http-request and same instance is shared for the life of that request.
when is it constructed by Micronaut ? Is it immutable ?
Across multiple requests I can see the same requestId ( expecting new UUID for every request)
Is it the right use-case for @RequestScope bean?
Advertisement
Answer
when is it constructed by Micronaut ?
A @RequestScope
bean is created during request processing, the first time the bean is needed.
Is it immutable ?
It could be. You get to decide if the bean is mutable or not when you write the class. As written in your example, RequestContext
is mutable. If you remove the updateRouteName
method, that bean would be immutable.
Is it the right use-case for @RequestScope bean?
I don’t think so, but that is really an opinion based question.
EDIT: Based On Comments Added Below
See the project at https://github.com/jeffbrown/rscope.
package rscope; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; @Controller("/") public class DemoController { private final DemoBean demoBean; public DemoController(DemoBean demoBean) { this.demoBean = demoBean; } @Get("/doit") public String doit() { return String.format("Bean identity: %d", demoBean.getBeanIdentity()); } }
package rscope; import io.micronaut.runtime.http.scope.RequestScope; @RequestScope public class DemoBean { public DemoBean() { } public int getBeanIdentity() { return System.identityHashCode(this); } }
package rscope; import io.micronaut.http.client.RxHttpClient; import io.micronaut.http.client.annotation.Client; import io.micronaut.test.annotation.MicronautTest; import org.junit.jupiter.api.Test; import javax.inject.Inject; import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @MicronautTest public class DemoControllerTest { @Inject @Client("/") RxHttpClient client; @Test public void testIndex() throws Exception { // these will contain the identity of the the DemoBean used to handle these requests String firstResponse = client.toBlocking().retrieve("/doit"); String secondResponse = client.toBlocking().retrieve("/doit"); assertTrue(firstResponse.matches("^Bean identity: \d*$")); assertTrue(secondResponse.matches("^Bean identity: \d*$")); // if you modify DemoBean to be @Singleton instead of // @RequestScope, this will fail because the same instance // will be used for both requests assertNotEquals(firstResponse, secondResponse); } }