5

This previous question may serve as a baseline for what "submodules" mean for the purpose of the current discussion: Play Framework [2.4.x] Working with Sub Modules

If you understand a Play submodule then given that context how does one enter the routing entry on the submodule to expose assets from a "public" folder?

Whenever I attempt to make a basic entry (as follows) my entire root module fails to compile a single route and yet I get no "usable" error or other indicator as to what might have happened.

GET   /assets/*file  controllers.Assets.at(path="/public", file)

The compiler errors occur even if I comment out the entry in the root project.

As all my sub modules controllers have a prefix I tried that (of course)

GET   /assets/*file  controllers.submodule.Assets.at(path="/public", file)

Alas that doesn't work either but at least I get a useful error telling me the type Assets is not a member of package controllers.submodule

Any suggestions?

PS: Yes I've also tried taking the entry out of the root's routing file in case it was just a name space collision...

Community
  • 1
  • 1
Techmag
  • 1,383
  • 13
  • 24

1 Answers1

4

You have to create an Assets controller in your submodule controllers package:

package controllers.submodule

class Assets extends AssetsBuilder(DefaultHttpErrorHandler)

Then declare a route for this controller in the router file (it should be named submodule.routes) of your submodule:

GET    /submodule/public/*file    controllers.submodule.Assets.versioned(path="/public", file: Asset)

It is better to prefix the route with the name of your submodule to avoid route colision in case you have other submodules name with static route entry.

One more thing: all your static files are hosted in the "lib" folder of your root module:

lib/submodule/css...
lib/submodule/js...

So you have to update your views like that:

<script type="text/javascript" src="@controllers.submodule.routes.Assets.versioned("lib/submodule/js/your-submodule-script.js")"></script>

EDIT: don't forget to add this to your route file (named routes) of your root module

-> / submodule.routes
Maxime
  • 191
  • 9
  • In the main routes file (the routes feel for the main project) I have this little gem: `-> /submoduleNAME submodule.Routes` which essentially gives an alias of the submodule from the external perspective. Curious as to whether or not that will apply but thinking out loud I suspect it doesn't even matter... – Techmag Sep 21 '15 at 15:23
  • And where might one find the error handler? `not enough arguments for constructor AssetsBuilder: (errorHandler: play.api.http.HttpErrorHandler)controllers.AssetsBuilder.` – Techmag Sep 21 '15 at 15:38
  • I didn't mentioned it but yes you have to add this line to the route file of your root module. I just edited my answer – Maxime Sep 21 '15 at 15:39
  • hmm...if you are using play 2.4 you should use `Assets extends AssetsBuilder(DefaultHttpErrorHandler) in the Asserts controller` – Maxime Sep 21 '15 at 15:45
  • Ah - that would be `play.api.http.DefaultHttpErrorHandler` -- compiles at least so now I'll see if it works... – Techmag Sep 21 '15 at 15:48
  • Strange - I can't seem to connect the dots to an actual (static) file. I do seem to get a different error at times however - one of `No router defined` instead of `Action not found` followed by the list of routes tried. I've tried both the `.at` and the `.versioned` methods along with may incantations of the path(s) on both ends of the routing statement. – Techmag Sep 21 '15 at 16:11
  • Currently hitting this: https://groups.google.com/forum/#!topic/play-framework/z3OKPdfyocM (which it seems you may have already accounted for...) – Techmag Sep 21 '15 at 19:00
  • This is not quiet what I'm seeing. First I have to change the raw URL as follows: http://localhost:9000/SUBMODULE_REF_1/assets/lib/SUBMODULE_REF_2/favicon.png SUBMODULE_REF_1 is the entry in the root routes file and SUBMODULE_REF_2 is the actual submodule name. I do NOT have to place the files into an actual directory called `lib` -- took me many hours to find a single file so I'm not sure the above answer is conveying the full extent of what needs to be done clearly. – Techmag Sep 21 '15 at 19:12
  • Actually you don't have to create a lib folder. Play generates all the static content for you into the `target/web/public/main/lib/submodule` folder for every submodule instead of `target/web/public/main` folder for the root module's static files. – Maxime Sep 22 '15 at 08:18
  • 2
    Your answer was helpful for me. However, there are two details I would suggest to look into: a) the route at the end is missing a slash, right? Should be "-> / submodule.routes". b) the 'object Assets ...' implies that InjectedRoutesGenerator setting is not used, which is now (Play 2.4) recommended. With InjectedRoutesGenerator it needs to be 'class Assets ...' to compile. – akauppi Dec 02 '15 at 06:20
  • 2
    @akauppi point b) of your remark helped me solved my problem as stated in http://stackoverflow.com/questions/33985108/play-framework-2-4-x-module-route-specific-name-fails-with-assets-is-not-a Feel free to put it as answer to my question, I'll be pleased to acknowledge it. – Patrick Refondini Dec 02 '15 at 07:39
  • @akauppi, you're right on your 2 points, I just edited the answer – Maxime Dec 03 '15 at 12:40