Back to Playframework

Writing Play Modules

documentation/manual/working/scalaGuide/advanced/extending/ScalaPlayModules.md

3.1.0-M94.0 KB
Original Source
<!--- Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com> -->

Writing Play Modules

Note: This page covers the new [[module system|ScalaDependencyInjection#Play-libraries]] to add functionality to Play.

The deprecated play.api.Plugin system is removed as of 2.5.x.

A [[module|ScalaDependencyInjection#Play-libraries]] can be written using any dependency injection framework. However, when you want to extend Play, you need to avoid dependencies on a specific framework so that your extension can work independently of the dependency injection. Play previously used the play.api.Plugin system for this purpose, but in 2.5.x, Plugins have been replaced with Play modules.

A Play module is a class that extends play.api.inject.Module and can be registered with Play without relying explicitly on a particular dependency injection framework. This allows everyone to use Play modules.

A list of Play modules are available in the [[module directory|ModuleDirectory]].

In addition, because Play uses Play modules for built-in functionality, a Play module must be used to replace or augment built-in functionality.

Creating and migrating Play modules

Creating a Play module is simple:

@module-definition

For more information, see the "Create a Module class" section of [[Plugins to Modules|PluginsToModules#Create-a-Module-class]].

Module Registration

By default, Play will load any class called Module that is defined in the root package (the "app" directory) or you can define them explicitly inside the reference.conf or the application.conf:

play.modules.enabled += "modules.MyModule"

Please see [[migration page|PluginsToModules#Wire-it-up]] and [[the dependency injection documentation|ScalaDependencyInjection#Play-libraries]] for more details.

Application Lifecycle

A module can detect when Play shutdown occurs by injecting the play.api.inject.ApplicationLifecycle trait into the singleton instance and adding a shutdown hook.

Please see the [[ApplicationLifecycle example|PluginsToModules#Create-a-Module-class]] and [[ApplicationLifecycle reference|ScalaDependencyInjection#Stopping/cleaning-up]] for more details.

Testing Play Modules

Modules can be tested using Play's built in test functionality, using the GuiceApplicationBuilder and adding a binding to the module.

@module-bindings

Please see [[Testing with Guice|ScalaTestingWithGuice#Bindings-and-Modules]] for more details.

Listing Existing Play Modules

The Modules.locate(env, conf) method will display a list of all available Play modules in an application.

Overriding Built-In Modules

There are some cases where Play provides a built-in module that must be overridden.

For example, [[Messages|ScalaI18N]] functionality is implemented by the MessagesApi trait and backed by DefaultMessagesApi. If you write a replacement class MyMessagesApi that extends MessagesApi, you can bind it with:

@builtin-module-definition

Testing Overrides

Testing the application should be done using the overrides method to replace the existing implementation:

@builtin-module-overrides

Registration Overrides

Because the I18nModule is loaded automatically in reference.conf, you must first [[disable|ScalaDependencyInjection#Excluding-modules]] the default module before adding the replacement module:

play.modules.disabled += "play.api.i18n.I18nModule"
play.modules.enabled += "modules.MyI18nModule"

You should not disable existing modules in reference.conf when publishing a Play module, as it may have unexpected consequences. Please see the [[migration page|PluginsToModules#Wire-it-up]] for details.