Question

Are there any examples of large multi module play framework (Scala) applications. For example, using multiple visual themes and serving different content based on theme. What is the best way to organise code for such applications.

Était-ce utile?

La solution

I think there are two distinct points in your question :

  • how to split a large play application into smaller, more manageable modules ?
  • how to dynamically choose different views for the same Action (i.e. having multiple theme to render the same data) ?

The first point is quite simple, although it's not clearly (AFAIK) documented in the online documentation. A play! module is built like a regular play application but without any configuration file. So basically, remove the conf/ folder of any application, publish it in your favorite repository, and you're ready to use that module as a dependency in another application/module.

The second point is a little trickier. Since play templates are statically compiled, changing views at runtime is something that is not supported out of the box, you'll have to come up with your own solution.

A first solution would be to use a different template engine, one that interprets templates at runtime this blog post explains how to use the scalate template engine in a play 2.X application.

Another solution would involve the use of runtime reflexion to select the right template at runtime, but at the expense of loosing some of the compile time safeguards (if the needed template is not present you'll have a runtime error, and not a compile time error like in a regular application).

A third solution would be to abstract templates and routes from your controllers (making them traits or abstract class) in a parent module, and then create one child application per different theme, each child application would only have to implement the abstract controller by providing the needed templates and routes :

// in the parent module
trait AbsCtrl extends Controller {
  val indexTemplate : (Foo, Bar) => Html // a template is like a function
                                         // from some models to Html
  val errorRoute : Call

  def index() = Action {
    request =>
      val foo = Foo()
      val bar = Bar()
      if(someCondition) Ok(indexTemplate(foo, bar))
      else Redirect(errorRoute)
  }
}

// in the child module 
object Ctrl extends AbsCtrl {
  // assuming you have a scala template named index that take the right arguments
  override val indexTemplate = views.html.index.render
  override val errorRoute = routes.Application.error()
}   

This solution is a bit more involved, it requires to have one application per theme which may not be acceptable in some contexts, but it retains the compile time safety, so it might be preferable compared to the previous one.

Last, you can choose to split your system in two different layers :

  • a business layer in your play application, with a simple REST API
  • a rendering layer, facing the end user, that'll use the business API and take care of the theme-specific rendering

You can use another technology to write the later one, for example, a simple node.js server that will let you leverage a javascript based template engine.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top