Is each Framework web request processed with a new instance of the controller with dependencies, but what about the static methods of the controller?

My questions relate to the life cycle of controllers in the Play platform for Java, if the controllers are stateless instances or have no state with static methods and how to use dependency injection in the controller code.

Each web request is processed by a new instance of the Play controller class, that is, can the storage status of the controller be in fields such as services entered into the controller’s constructor? (where does the documentation explain?)

Is the playback structure changed from earlier versions (and if so, in which version?) Regarding the fact that the controllers are stateless or stateless controllers with static methods?

Where can you see code examples on how the infrastructure deploys services to a controller instance when using a state controller and an example of how to inject services into a static controller method?

As for the latter, that is, injections into a static method, I believe that this should either be a parameter of the method to be added by the frameworks, or if this is not possible, you may have to use the service locator from the method, for example, create an instance of the Guice module class and then use "injector.getInstance" from the static controller method.

This issue is addressed in the Dependency Injection Controllers section of the following page:

https://www.playframework.com/documentation/2.4.x/JavaDependencyInjection

However, it does not show with the code how to actually embed services in the controller instance (but, probably, in the same way as other "components", i.e. with the @Inject annotation), and, of course, it does not currently show How to use DI with a static controller.

I got confused about these things because I did not find the documentation in which my questions were clear, and I also read in the Play Book (since 2013) that controller methods should be programmed as stateless, and controller methods should be static.

However, if I now use the activator to create a Play application for Java with the latest version of Play (2.4.6), I see that the generated Controller method (Application.index) is not static. In addition, on the next page of the documentation, the controller method is NOT static: https://www.playframework.com/documentation/2.4.x/JavaActions

This is confusing, and since it is VERY important to understand whether each request is processed by the controller instance or not (i.e. if the state can be used), I think that this should be better described on the controller / actions page than the current documentation ( link above) which does not explain this.

The dependency injection documentation covers the topic of static and non-static methods in the section "Dependency Injection Controllers" which mention the "static route generator", but I think this should be better explained, including code examples.

If someone from the Play team reads this question, please add some information to the above related pages, for example, please indicate (if I understood correctly) that in previous versions of Play the controller methods were static and for these versions you should never store state in fields, but in later versions (starting with version x?) each request is processed by the controller instance and therefore can use state (for example, designer parameters entered by the framework).

Please also provide code examples regarding injections used with static controller methods and insertion into state controller instances with one instance for each request.

In the “Component Life Cycle” section of the dependency entry page, only “components” are mentioned, but I think that it should also be explicit about the life cycle of the controller and its introduction, since it is such fundamental and important knowledge that should be clearly communicated to all developers to avoid errors caused by misunderstandings about being restrained or not.

+4
source share
2 answers

Each web request is processed by a new instance of the Play controller class, that is, can the storage status of the controller be in fields such as services entered into the controller’s constructor? (where does the documentation explain?)

As far as I can tell, controllers are singleton objects by default . This is not explicitly documented, but it implies that controller instances are reused. See the Migration Guide for Playframework 2.4 :

The added route generator also supports the @ operator on routes, but has a slightly different meaning (since everything is entered), if you prefix the controller with @, instead of having this controller directly entered, the JSR 330 provider for this controller will be entered. This can be used, for example, to troubleshoot issues with circular dependency, or if you want a new action to be created per request .

Also, mark this assessment made by James Roper (core game handler) if the controllers are solid or not:

Not really - if you use Guice, every time something is entered, a new instance will be created by default. However, the router is singleton, and therefore, by association, the controllers it calls are singleton . But if you enter the controller in another place, it will be created for this component again.

This suggests that the default is to reuse controller instances when responding to requests, and if you want a new action for each request, you need to use the syntax described in the migration guide. But ... since I am more inclined to prove and try something instead of just believing, I created a simple controller to test this statement:

package controllers import play.api._ import play.api.mvc._ class Application extends Controller { def index = Action { println(this) Ok(views.html.index("Your new application is ready.")) } } 

Running multiple requests for this action displays the same object identifier for all requests made. But, if I use the @ operator on my routes, I start to get different identifiers for each request. So, yes, controllers are the (kind of) singleton by default .

Is the playback structure changed from earlier versions (and if so, in which version?) Regarding the fact that the controllers are stateless or stateless controllers with static methods?

By default, Play always stands for stateless controllers, as you can see on the project home page :

The game is based on light, stagnant , web architecture.

This has not changed. Thus, you should not use the fields / properties of controllers to store data that changes over time / queries. Instead, simply use the fields / properties of the controllers to maintain a reference to other components / services that are also stateless.

Where can you see code examples on how the infrastructure deploys services to a controller instance when using a state controller and an example of how to inject services into a static controller method?

As for the code examples, the activator pattern repository is the place to go. Here are some examples that use dependency injection at the controller level:

Dependency injection with static methods is not supported, and so Playframework stills offers an old apis for use with static methods. The rule of thumb: the choice between DI and static methods. Trying to use both options will simply add complexity to your application.

+3
source

Ok, thanks marcospereira. I also confirmed that you really get different instances (different toString values ​​that can be printed / registered in the controller method) of the controller for each request.

For those interested, the solution (to get different instances of the controller class for each request) should use, for example, the following:

 GET / @controllers.Application.index() 

instead of the following:

 GET / controllers.Application.index() 

in the file "conf / routes" And also use the following:

 routesGenerator := InjectedRoutesGenerator 

instead of the following:

 routesGenerator := StaticRoutesGenerator 

in the file "build.sbt"

Regarding the claim that Play has a "stateless" architecture: Maybe I'm wrong, but as far as I understand the terminology, stateless means that the web server does not save any state between requests? The word "stateless" does not mean that the controller instance cannot use fields, for example. entered into the constructor. If the entered object is stored as a field in the controller, then this field is the "state" of the controller. Therefore, even if you use the "InjectedRoutesGenerator" and the "@" prefix to get the "states" of the controller instances, the injected "state" is saved in only one request, so you can still say that the framework itself is "stateless" since the server is not keeps state between several requests. Please correct me if I misunderstood that the game is stateless.

0
source

Source: https://habr.com/ru/post/1247158/


All Articles