Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support Java ApplicationLoaders; add GuiceApplicationLoader docs
This will mostly be useful because it makes it easier to override the GuiceApplicationLoader.
- Loading branch information
1 parent
1cbf3de
commit 22c115d
Showing
15 changed files
with
428 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 57 additions & 0 deletions
57
framework/src/play-java/src/main/java/play/inject/guice/GuiceApplicationLoader.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
/* | ||
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com> | ||
*/ | ||
package play.inject.guice; | ||
|
||
import play.api.inject.guice.GuiceableModule; | ||
import play.libs.Scala; | ||
import play.Application; | ||
import play.ApplicationLoader; | ||
|
||
/** | ||
* An ApplicationLoader that uses Guice to bootstrap the application. | ||
* | ||
* Subclasses can override the <code>builder</code> and <code>overrides</code> | ||
* methods. | ||
*/ | ||
public class GuiceApplicationLoader implements ApplicationLoader { | ||
|
||
/** | ||
* The initial builder to start construction from. | ||
*/ | ||
protected final GuiceApplicationBuilder initialBuilder; | ||
|
||
public GuiceApplicationLoader() { | ||
this(new GuiceApplicationBuilder()); | ||
} | ||
|
||
public GuiceApplicationLoader(GuiceApplicationBuilder initialBuilder) { | ||
this.initialBuilder = initialBuilder; | ||
} | ||
|
||
@Override | ||
public final Application load(ApplicationLoader.Context context) { | ||
return builder(context).build(); | ||
} | ||
|
||
/** | ||
* Construct a builder to use for loading the given context. | ||
*/ | ||
protected GuiceApplicationBuilder builder(ApplicationLoader.Context context) { | ||
return initialBuilder | ||
.in(context.environment()) | ||
.loadConfig(context.initialConfiguration()) | ||
.overrides(overrides(context)); | ||
} | ||
|
||
/** | ||
* Override some bindings using information from the context. The default | ||
* implementation of this method provides bindings that most applications | ||
* should include. | ||
*/ | ||
protected GuiceableModule[] overrides(ApplicationLoader.Context context) { | ||
scala.collection.Seq<GuiceableModule> seq = play.api.inject.guice.GuiceApplicationLoader$.MODULE$.defaultOverrides(context.underlying()); | ||
return Scala.asArray(GuiceableModule.class, seq); | ||
} | ||
|
||
} |
70 changes: 70 additions & 0 deletions
70
framework/src/play-java/src/test/java/play/inject/guice/GuiceApplicationLoaderTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
/* | ||
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com> | ||
*/ | ||
package play.inject.guice; | ||
|
||
import com.google.common.collect.ImmutableMap; | ||
import org.junit.Rule; | ||
import org.junit.rules.ExpectedException; | ||
import org.junit.Test; | ||
import play.Application; | ||
import play.ApplicationLoader; | ||
import play.Configuration; | ||
import play.Environment; | ||
import play.libs.Scala; | ||
|
||
import static org.hamcrest.CoreMatchers.*; | ||
import static org.junit.Assert.*; | ||
import static play.inject.Bindings.bind; | ||
|
||
public class GuiceApplicationLoaderTest { | ||
|
||
@Rule | ||
public ExpectedException exception = ExpectedException.none(); | ||
|
||
private ApplicationLoader.Context fakeContext() { | ||
return ApplicationLoader.Context.create(Environment.simple()); | ||
} | ||
|
||
@Test | ||
public void additionalModulesAndBindings() { | ||
GuiceApplicationBuilder builder = new GuiceApplicationBuilder() | ||
.bindings(new AModule()) | ||
.bindings(bind(B.class).to(B1.class)); | ||
ApplicationLoader loader = new GuiceApplicationLoader(builder); | ||
Application app = loader.load(fakeContext()); | ||
|
||
assertThat(app.injector().instanceOf(A.class), instanceOf(A1.class)); | ||
assertThat(app.injector().instanceOf(B.class), instanceOf(B1.class)); | ||
} | ||
|
||
@Test | ||
public void extendLoaderAndSetConfiguration() { | ||
ApplicationLoader loader = new GuiceApplicationLoader() { | ||
@Override | ||
protected GuiceApplicationBuilder builder(ApplicationLoader.Context context) { | ||
Configuration extra = new Configuration("a = 1"); | ||
return initialBuilder | ||
.in(context.environment()) | ||
.loadConfig(extra.withFallback(context.initialConfiguration())) | ||
.overrides(overrides(context)); | ||
} | ||
}; | ||
Application app = loader.load(fakeContext()); | ||
|
||
assertThat(app.configuration().getInt("a"), is(1)); | ||
} | ||
|
||
public static interface A {} | ||
public static class A1 implements A {} | ||
|
||
public static class AModule extends com.google.inject.AbstractModule { | ||
public void configure() { | ||
bind(A.class).to(A1.class); | ||
} | ||
} | ||
|
||
public static interface B {} | ||
public static class B1 implements B {} | ||
|
||
} |
139 changes: 139 additions & 0 deletions
139
framework/src/play/src/main/java/play/ApplicationLoader.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,139 @@ | ||
/* | ||
* Copyright (C) 2009-2015 Typesafe Inc. <http://www.typesafe.com> | ||
*/ | ||
package play; | ||
|
||
import java.util.Collections; | ||
import java.util.Map; | ||
import play.core.SourceMapper; | ||
import play.core.DefaultWebCommands; | ||
import play.libs.Scala; | ||
|
||
/** | ||
* Loads an application. This is responsible for instantiating an application given a context. | ||
* | ||
* Application loaders are expected to instantiate all parts of an application, wiring everything together. They may | ||
* be manually implemented, if compile time wiring is preferred, or core/third party implementations may be used, for | ||
* example that provide a runtime dependency injection framework. | ||
* | ||
* During dev mode, an ApplicationLoader will be instantiated once, and called once, each time the application is | ||
* reloaded. In prod mode, the ApplicationLoader will be instantiated and called once when the application is started. | ||
* | ||
* Out of the box Play provides a Java and Scala default implementation based on Guice. The Java implementation is the | ||
* {@link play.inject.guice.GuiceApplicationLoader} and the Scala implementation is {@link play.api.inject.guice.GuiceApplicationLoader}. | ||
* | ||
* A custom application loader can be configured using the `application.loader` configuration property. | ||
* Implementations must define a no-arg constructor. | ||
*/ | ||
public interface ApplicationLoader { | ||
|
||
/** | ||
* Load an application given the context. | ||
*/ | ||
Application load(ApplicationLoader.Context context); | ||
|
||
/** | ||
* The context for loading an application. | ||
*/ | ||
final static class Context { | ||
private final play.api.ApplicationLoader.Context underlying; | ||
private final Configuration initialConfiguration; | ||
private final Environment environment; | ||
|
||
/** | ||
* The context for loading an application. | ||
* | ||
* @param underlying The Scala context that is being wrapped. | ||
*/ | ||
public Context(play.api.ApplicationLoader.Context underlying) { | ||
this.underlying = underlying; | ||
this.environment = new Environment(underlying.environment()); | ||
this.initialConfiguration = new Configuration(underlying.initialConfiguration()); | ||
} | ||
|
||
/** | ||
* Get the wrapped Scala context. | ||
*/ | ||
public play.api.ApplicationLoader.Context underlying() { | ||
return underlying; | ||
} | ||
|
||
/** | ||
* Get the environment from the context. | ||
*/ | ||
public Environment environment() { | ||
return environment; | ||
} | ||
|
||
/** | ||
* Get the configuration from the context. This configuration is not necessarily the same | ||
* configuration used by the application, as the ApplicationLoader may, through it's own | ||
* mechanisms, modify it or completely ignore it. | ||
*/ | ||
public Configuration initialConfiguration() { | ||
return initialConfiguration; | ||
} | ||
|
||
/** | ||
* Create a new context with a different environment. | ||
*/ | ||
public Context withEnvironment(Environment environment) { | ||
play.api.ApplicationLoader.Context scalaContext = new play.api.ApplicationLoader.Context( | ||
environment.underlying(), | ||
underlying.sourceMapper(), | ||
underlying.webCommands(), | ||
underlying.initialConfiguration()); | ||
return new Context(scalaContext); | ||
} | ||
|
||
/** | ||
* Create a new context with a different configuration. | ||
*/ | ||
public Context withConfiguration(Configuration initialConfiguration) { | ||
play.api.ApplicationLoader.Context scalaContext = new play.api.ApplicationLoader.Context( | ||
underlying.environment(), | ||
underlying.sourceMapper(), | ||
underlying.webCommands(), | ||
initialConfiguration.getWrappedConfiguration()); | ||
return new Context(scalaContext); | ||
} | ||
|
||
// The following static methods are on the Context inner class rather | ||
// than the ApplicationLoader interface because https://issues.scala-lang.org/browse/SI-8852 | ||
// wasn't fixed until Scala 2.11.3, and at the time of writing we need | ||
// to support Scala 2.10. | ||
|
||
/** | ||
* Create an application loading context. | ||
* | ||
* Locates and loads the necessary configuration files for the application. | ||
* | ||
* @param environment The application environment. | ||
* @param initialSettings The initial settings. These settings are merged with the settings from the loaded | ||
* configuration files, and together form the initialConfiguration provided by the context. It | ||
* is intended for use in dev mode, to allow the build system to pass additional configuration | ||
* into the application. | ||
*/ | ||
public static Context create(Environment environment, Map<String, String> initialSettings) { | ||
play.api.ApplicationLoader.Context scalaContext = play.api.ApplicationLoader$.MODULE$.createContext( | ||
environment.underlying(), | ||
Scala.asScala(initialSettings), | ||
Scala.<SourceMapper>None(), | ||
new DefaultWebCommands()); | ||
return new Context(scalaContext); | ||
} | ||
|
||
/** | ||
* Create an application loading context. | ||
* | ||
* Locates and loads the necessary configuration files for the application. | ||
* | ||
* @param environment The application environment. | ||
*/ | ||
public static Context create(Environment environment) { | ||
return create(environment, Collections.emptyMap()); | ||
} | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.