Reputation: 482
I have an APIController class defined with a @RestController
annotation, which holds several REST services, defined with the @RequestMapping
annotation.
I'm looking for a way to define a "static" integer which will be initialized to 0 on every REST call.
My goal is to define a singleton with a scope of a REST instance / call, and not with the scope of the entire application.
For example: I have a getData
REST, which calls the internal function getSingletonData
twice. First call to getSingletonData
will return 1 and the second will return 2.
Once another user will call the getData
rest service, the same function getSingletonData
will return again 1 and 2, and not 3 and 4 (which will happen in case the internal integer variable will be defined as static?).
I know I can just define the variable as a local variable inside the REST service, but I want to avoid passing it as a parameter to many functions, and I would like the class to be a singleton (the class just returns sequential numbers whenever asked, in the scope of that specific REST call).
Upvotes: 2
Views: 2388
Reputation: 78589
Well, one way to solve your problem is by defining a request-based bean. You see, Spring components may have different scopes: e.g. singleton, prototype, request, and session.
So, you could define a bean whose scope is the "request" itself. By doing this you'd get a fresh instance of it injected per request in e.g. your controller.
You could define such a data provider somewhat as follows:
@Configuration
public class DataProviderConfiguration {
@Bean
@Scope(scopeName = WebApplicationContext.SCOPE_REQUEST,
proxyMode = ScopedProxyMode.INTERFACES)
public Supplier<Integer> getRequestDataProvider() {
AtomicInteger value = new AtomicInteger();
return value::incrementAndGet;
}
}
And then in your controller, you would get an instance of it injected per request using classical injection.
@RestController
public class DataProviderController {
@Autowired
private Supplier<Integer> requestDataProvider;
@GetMapping("/answers")
public Integer[] getAnswer() {
return new Integer[]{requestDataProvider.get(), requestDataProvider.get()};
}
}
And this will consistently produce the result [1,2]
per every request, which seems to be what you wanted to achieve.
Upvotes: 3