Skip to content

Commit

Permalink
Add documentation to point people to public modules.
Browse files Browse the repository at this point in the history
  • Loading branch information
wsargent committed Feb 4, 2016
1 parent 0084c83 commit 62a903b
Show file tree
Hide file tree
Showing 11 changed files with 282 additions and 5 deletions.
4 changes: 4 additions & 0 deletions documentation/manual/ModuleDirectory.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
<!--- Copyright (C) 2009-2016 Typesafe Inc. <http://www.typesafe.com> -->
# Play modules

Play uses public modules to augment built-in functionality.

To create your own public module or to migrate from a `play.api.Plugin`, please see [[ScalaPlayModules]] or [[JavaPlayModules]].

## API hosting

### swagger-play
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<!--- Copyright (C) 2009-2016 Typesafe Inc. <http://www.typesafe.com> -->
# Writing Play Modules

> **NOTE**: This page covers the new [[module system|JavaDependencyInjection#Play-libraries]] to add new functionality to Play.
>
> The deprecated `play.Plugin` system is removed as of 2.5.x.
A [[module|JavaDependencyInjection#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.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`](api/scala/play/api/inject/Module.html) 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-class-api](code/javaguide/advanced/extending/MyApi.java)

@[module-class-definition](code/javaguide/advanced/extending/MyModule.java)

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

## Module registration

Play modules are registered through Play's configuration system by adding the Play module into `reference.conf`:

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

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

## Application lifecycle

A module can detect when Play shutdown occurs by injecting the [`play.inject.ApplicationLifecycle`](api/java/play/inject/ApplicationLifecycle.html) interface into the singleton instance and adding a shutdown hook.

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

## Testing Play modules

Play Modules can be tested using Play's built in test functionality, by using the [`GuiceApplicationBuilder`](api/java/play/inject/guice/GuiceApplicationBuilder.html) and adding a binding to the module.

@[module-class-binding](code/javaguide/advanced/extending/JavaExtendingPlay.java)

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

## Listing existing Play modules

The [`Modules.locate(env, conf)`](api/scala/play/api/inject/Modules$.html) method will display a list of all available Play modules in an application. There is no corresponding Java class.

## Overriding built-in modules

There are some cases where Play provides a built-in module that must be overridden. In these cases, the Java implementation is a wrapper over the Scala one, and so it's usually more convenient to override the Scala implementation directly.
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<!--- Copyright (C) 2009-2016 Typesafe Inc. <http://www.typesafe.com> -->
# Writing Plugins

> TODO
> **NOTE**: The `play.Plugin` API was deprecated in 2.4.x and is removed as of 2.5.x.
>
> Please use [[Play Modules|JavaPlayModules]], and see the [[Plugins to Modules|PluginsToModules]] page for migration details.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2009-2016 Typesafe Inc. <http://www.typesafe.com>
*/
package javaguide.advanced.extending;

import org.junit.Test;

import play.Application;
import play.inject.guice.GuiceApplicationBuilder;

import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;

public class JavaExtendingPlay {

@Test
public void testModule() throws Exception {
// #module-class-binding
Application application = new GuiceApplicationBuilder()
.bindings(new MyModule())
.build();
// #module-class-binding
MyApi api = application.injector().instanceOf(MyApi.class);

assertNotNull(api);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright (C) 2009-2016 Typesafe Inc. <http://www.typesafe.com>
*/
package javaguide.advanced.extending;

// #module-class-api
public class MyApi {

}
// #module-class-api
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (C) 2009-2016 Typesafe Inc. <http://www.typesafe.com>
*/
package javaguide.advanced.extending;

import play.api.Configuration;
import play.api.Environment;
import play.api.inject.Binding;
import scala.collection.Seq;

// #module-class-definition
public class MyModule extends play.api.inject.Module {
public Seq<Binding<?>> bindings(Environment environment, Configuration configuration) {
return seq(
bind(MyApi.class).toSelf()
);
}
}
// #module-class-definition
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
JavaPlugins:Writing plugins
JavaPlayModules:Writing Play modules
JavaPlugins:Migrating from Plugins API
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<!--- Copyright (C) 2009-2016 Typesafe Inc. <http://www.typesafe.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`](api/scala/play/api/inject/Module.html) 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](code/ScalaExtendingPlay.scala)

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

## Module Registration

Play modules are registered through Play's configuration system by adding the Play module into `reference.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`]((api/scala/play/api/inject/ApplicationLifecycle.html) 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](code/ScalaExtendingPlay.scala)

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

## Listing Existing Play Modules

The [`Modules.locate(env, conf)`](api/scala/play/api/inject/Modules$.html) 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](api/scala/play/api/i18n/MessagesApi.html) and backed by [DefaultMessagesApi](api/scala/play/api/i18n/DefaultMessagesApi.html). If you write a replacement class `MyMessagesApi` that extends `MessagesApi`, you can bind it with:

@[builtin-module-definition](code/ScalaExtendingPlay.scala)

### Testing Overrides

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

@[builtin-module-overrides](code/ScalaExtendingPlay.scala)

### 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.
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<!--- Copyright (C) 2009-2016 Typesafe Inc. <http://www.typesafe.com> -->
# Writing Plugins

> TODO
> **NOTE**: The `play.api.Plugin` API was deprecated in 2.4.x and is removed as of 2.5.x.
>
> Please use [[Play Modules|ScalaPlayModules]], and see the [[Plugins to Modules|PluginsToModules]] page for migration details.
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/*
* Copyright (C) 2009-2016 Typesafe Inc. <http://www.typesafe.com>
*/
package scalaguide.advanced.extending

import org.specs2.mutable.Specification
import play.api._
import play.api.i18n._
import play.api.inject.guice.GuiceApplicationBuilder
import play.api.mvc.Result
import play.mvc.Http.RequestHeader


object ScalaExtendingPlay extends Specification {

class MyMessagesApi extends MessagesApi {
override def messages: Map[String, Map[String, String]] = ???
override def preferred(candidates: Seq[Lang]): Messages = ???
override def preferred(request: mvc.RequestHeader): Messages = ???
override def preferred(request: RequestHeader): Messages = ???
override def langCookieHttpOnly: Boolean = ???
override def clearLang(result: Result): Result = ???
override def langCookieSecure: Boolean = ???
override def langCookieName: String = ???
override def setLang(result: Result, lang: Lang): Result = ???
override def apply(key: String, args: Any*)(implicit lang: Lang): String = ???
override def apply(keys: Seq[String], args: Any*)(implicit lang: Lang): String = ???
override def isDefinedAt(key: String)(implicit lang: Lang): Boolean = ???
override def translate(key: String, args: Seq[Any])(implicit lang: Lang): Option[String] = ???
}

// #module-definition
class MyCode {
// add functionality here
}

class MyModule extends play.api.inject.Module {
def bindings(environment: Environment, configuration: Configuration) = {
Seq(bind[MyCode].toInstance(new MyCode))
}
}
// #module-definition

// #builtin-module-definition
class MyI18nModule extends play.api.inject.Module {
def bindings(environment: Environment, configuration: Configuration) = {
Seq(
bind[Langs].to[DefaultLangs],
bind[MessagesApi].to[MyMessagesApi]
)
}
}
// #builtin-module-definition

"Extending Play" should {

"adds a module" in {
// #module-bindings
val application = new GuiceApplicationBuilder()
.bindings(new MyModule)
.build()
val myCode = application.injector.instanceOf(classOf[MyCode])
myCode must beAnInstanceOf[MyCode]
// #module-bindings
}

"overrides a built-in module" in {
// #builtin-module-overrides
val application = new GuiceApplicationBuilder()
.overrides(new MyI18nModule)
.build()
// #builtin-module-overrides
val messageApi = application.injector.instanceOf(classOf[MessagesApi])
messageApi must beAnInstanceOf[MyMessagesApi]
}

}


}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
ScalaPlugins:Writing plugins
ScalaPlayModules:Writing Play modules
ScalaPlugins:Migrating from Plugins API

0 comments on commit 62a903b

Please sign in to comment.