Search code examples
playframeworkroutescontrollers

Where is the default controllers package configured for play framework 2.6?


I am re-introducing myself to Play Framework, and having not touched it for a while, re-acquainting myself with the important basics. I'm looking at Java for the moment, but this question really has nothing to do with Java or Scala. I'm using Play Framework version 2.6.11

I would like to better understand how the controllers are setup; i.e., more precisely, what specifies the 'controllers' package as the default package where controllers should be placed.

For example, the first starter example that one can run sees a directory structure like this:

app/controllers
app/views
app/services

There is a Java file in the controllers package:

CountController.java

The routes file shows an entry:

GET     /count                      controllers.CountController.count

and in the file welcome.scala.html (in the views package) one can find a dynamic link, which is coded like this:

@routes.CountController.count

which references a member in the routes class in the target.

As one can notice, the reference from the views do not seem to need to fully qualify the method. i.e., for "@routes.CountController.count" the controllers package seems to be implicit.

So my first question to myself was; is this hard-coded somewhere. This is simply convention, and there is no way to change it or extend it?

Digging around the documentation, I find it very difficult to discover any information on this.

So, to discover more, I try to create a custom package.

I create, at the same level as controllers, views, services etc, a package 'altcont' and place a controller class 'HelloWorld.java' inside.

I create an entry in the routes file:

GET     /helloWorld                 altcont.HelloWorld.greeting

and I attempt to reference it all from one of the other pages; first like this:

"@routes.HelloWorld.greeting"

This did not work.

OK. So there is no magic discovering controllers in arbitrary packages, and it is not somehow parsing the fully qualified class name from the routes file to discover it. It simply can't find it. Fine. So I try this:

"@altcont.routes.HelloWorld.greeting"

This worked!!!

Great. OK, so I understand it a bit better. Yet, it still implies that

there is, somewhere, something telling play that if a package is not specified to look first in the controllers package.

Is my previous statement correct? Is this configurable? Is this hard-coded convention? Where can I find this documented?

thanks!


Solution

  • I would like to better understand how the controllers are setup; i.e., more precisely, what specifies the 'controllers' package as the default package where controllers should be placed.

    It is just a convention, and nothing more than that. So, if you want to place your controllers inside com.mycompany.controllers, you are good to go. Of course, you need to consider code generation aspects, like reverse routing. But this is not a problem in any way.

    As one can notice, the reference from the views do not seem to need to fully qualify the method. i.e., for "@routes.CountController.count" the controllers package seems to be implicit.

    This is because @routes.CountController.count comes from the reverse router. The fully qualified name is controllers.routes.CountController, but controllers._ is already imported by default at every view.

    If you want to use a package like com.mycompany.controllers, then the reverse router will be com.mycompany.controllers.routes.MyController.myAction.

    Great. OK, so I understand it a bit better. Yet, it still implies that

    there is, somewhere, something telling play that if a package is not specified to look first in the controllers package.

    There is no such thing. They are just regular classes inside a regular package. The stronger convention is given by the reverse router generation, as you already noticed.