diff --git a/documentation/manual/production.textile b/documentation/manual/production.textile
index 9876b0063f..4a9b93c9f7 100644
--- a/documentation/manual/production.textile
+++ b/documentation/manual/production.textile
@@ -6,6 +6,16 @@ h2. application.conf
First off, the best way to specify production mode is to give a specific ID to your production framework. Let’s pick @production@ as an example. Refer "manage application.conf in several environments":ids to see how.
+h3. Specifying an alternative configuration file
+
+To force a different @application.conf@ file you can use the @config.file@ system property.
+
+bc. play run -Dconfig.file=/etc/play/config/external-conf-file.conf
+
+These system property specify a replacement for the default @conf/application.conf@ file, not an addition.
+
+NB: Note that if you use the @include
feature in your application.conf file, remember that they are loaded from the relative path of your @application.conf@ file.
+
h3. Set the framework in prod mode:
bc. %production.application.mode=prod
diff --git a/framework/src/play/Play.java b/framework/src/play/Play.java
index e4d0bc1634..fa491ced26 100644
--- a/framework/src/play/Play.java
+++ b/framework/src/play/Play.java
@@ -363,7 +363,9 @@ private static Properties readOneConfigurationFile(String filename, Set
Properties propsFromFile=null;
VirtualFile appRoot = VirtualFile.open(applicationPath);
- conf = appRoot.child("conf/" + filename);
+ conf = VirtualFile.open(System.getProperty("config.file", applicationPath + "/conf/" + filename));
+ Logger.info("Load application config file : %s", conf.getRealFile().getAbsolutePath());
+
try {
propsFromFile = IO.readUtf8Properties(conf.inputstream());
} catch (RuntimeException e) {
diff --git a/samples-and-tests/external-conf-file.conf b/samples-and-tests/external-conf-file.conf
new file mode 100644
index 0000000000..37a1b55846
--- /dev/null
+++ b/samples-and-tests/external-conf-file.conf
@@ -0,0 +1,217 @@
+# This is the main configuration file for the application.
+# ~~~~~
+application.name=external-conf-file
+
+# Application mode
+# ~~~~~
+# Set to dev to enable instant reloading and other development help.
+# Otherwise set to prod.
+application.mode=dev
+%prod.application.mode=prod
+
+# Secret key
+# ~~~~~
+# The secret key is used to secure cryptographics functions
+# If you deploy your application to several instances be sure to use the same key !
+application.secret=J0QCjINUPKguFSYHgK1KSXAbdAcJM6lFa1KXuBQvmO0U8tQvLtNRJm65zQXTWF4Q
+
+# i18n
+# ~~~~~
+# Define locales used by your application.
+# You can then place localized messages in conf/messages.{locale} files
+# application.langs=fr,en,ja
+
+# Date format
+# ~~~~~
+date.format=yyyy-MM-dd
+# date.format.fr=dd/MM/yyyy
+
+# Server configuration
+# ~~~~~
+# If you need to change the HTTP port, uncomment this (default is set to 9000)
+http.port=9876
+#
+# By default the server listen for HTTP on the wilcard address.
+# You can restrict this.
+# http.address=127.0.0.1
+#
+# Use this if you don't host your Play application at the root of the domain
+# you're serving it from. This parameter has no effect when deployed as a
+# war, because the path will be handled by the application server.
+# http.path=/
+
+# Session configuration
+# ~~~~~~~~~~~~~~~~~~~~~~
+# By default, session will be written to the transient PLAY_SESSION cookie.
+# The cookies are not secured by default, only set it to true
+# if you're serving your pages through https.
+# application.session.cookie=PLAY
+# application.session.maxAge=1h
+# application.session.secure=false
+
+# Session/Cookie sharing between subdomain
+# ~~~~~~~~~~~~~~~~~~~~~~
+# By default a cookie is only valid for a specific domain. By setting
+# application.defaultCookieDomain to '.example.com', the cookies
+# will be valid for all domains ending with '.example.com', ie:
+# foo.example.com and bar.example.com
+# application.defaultCookieDomain=.example.com
+
+# JVM configuration
+# ~~~~~
+# Define which port is used by JPDA when application is in debug mode (default is set to 8000)
+# jpda.port=8000
+#
+# Java source level => 1.5, 1.6 or 1.7 (experimental)
+# java.source=1.5
+
+# Log level
+# ~~~~~
+# Specify log level for your application.
+# If you want a very customized log, create a log4j.properties file in the conf directory
+# application.log=INFO
+#
+# More logging configuration
+# application.log.path=/log4j.properties
+# application.log.system.out=off
+
+# Database configuration
+# ~~~~~
+# Enable a database engine if needed.
+#
+# To quickly set up a development database, use either:
+# - mem : for a transient in memory database (H2 in memory)
+# - fs : for a simple file written database (H2 file stored)
+# db=mem
+#
+# To connect to a local MySQL5 database, use:
+# db=mysql://user:pwd@host/database
+#
+# To connect to a local PostgreSQL9 database, use:
+# db=postgres://user:pwd@host/database
+#
+# If you need a full JDBC configuration use the following :
+# db.url=jdbc:postgresql:database_name
+# db.driver=org.postgresql.Driver
+# db.user=root
+# db.pass=secret
+#
+# Connections pool configuration :
+# db.pool.timeout=1000
+# db.pool.maxSize=30
+# db.pool.minSize=10
+#
+# If you want to reuse an existing Datasource from your application server, use:
+# db=java:/comp/env/jdbc/myDatasource
+#
+# When using an existing Datasource, it's sometimes needed to destroy it when
+# the application is stopped. Depending on the datasource, you can define a
+# generic "destroy" method :
+# db.destroyMethod=close
+
+# JPA Configuration (Hibernate)
+# ~~~~~
+#
+# Specify the custom JPA dialect to use here (default to guess):
+# jpa.dialect=org.hibernate.dialect.PostgreSQLDialect
+#
+# Specify the ddl generation pattern to use. Set to none to disable it
+# (default to update in DEV mode, and none in PROD mode):
+# jpa.ddl=update
+#
+# Debug SQL statements (logged using DEBUG level):
+# jpa.debugSQL=true
+#
+# You can even specify additional hibernate properties here:
+# hibernate.use_sql_comments=true
+# ...
+#
+# Store path for Blob content
+attachments.path=data/attachments
+
+# Memcached configuration
+# ~~~~~
+# Enable memcached if needed. Otherwise a local cache is used.
+# memcached=enabled
+#
+# Specify memcached host (default to 127.0.0.1:11211)
+# memcached.host=127.0.0.1:11211
+#
+# Or you can specify multiple host to build a distributed cache
+# memcached.1.host=127.0.0.1:11211
+# memcached.2.host=127.0.0.1:11212
+#
+# Use plain SASL to authenticate for memcached
+# memcached.user=
+# memcached.password=
+
+# HTTP Response headers control for static files
+# ~~~~~
+# Set the default max-age, telling the user's browser how long it should cache the page.
+# Default is 3600 (one hour). Set it to 0 to send no-cache.
+# This is only read in prod mode, in dev mode the cache is disabled.
+# http.cacheControl=3600
+
+# If enabled, Play will generate entity tags automatically and send a 304 when needed.
+# Default is true, set it to false to deactivate use of entity tags.
+# http.useETag=true
+
+# Custom mime types
+# mimetype.xpi=application/x-xpinstall
+
+# WS configuration
+# ~~~~~
+# Default engine is Async Http Client, uncomment to use
+# the JDK's internal implementation
+# webservice = urlfetch
+# If you need to set proxy params for WS requests
+# http.proxyHost = localhost
+# http.proxyPort = 3128
+# http.proxyUser = jojo
+# http.proxyPassword = jojo
+
+# Mail configuration
+# ~~~~~
+# Default is to use a mock Mailer
+mail.smtp=mock
+
+# Or, specify mail host configuration
+# mail.smtp.host=127.0.0.1
+# mail.smtp.user=admin
+# mail.smtp.pass=
+# mail.smtp.channel=ssl
+
+# Url-resolving in Jobs
+# ~~~~~~
+# When rendering templates with reverse-url-resoling (@@{..}) in Jobs (which do not have an inbound Http.Request),
+# ie if sending a HtmlMail, Play need to know which url your users use when accessing your app.
+# %test.application.baseUrl=http://localhost:9000/
+# %prod.application.baseUrl=http://www.yourdomain.com/
+
+# Jobs executor
+# ~~~~~~
+# Size of the Jobs pool
+# play.jobs.pool=10
+
+# Execution pool
+# ~~~~~
+# Default to 1 thread in DEV mode or (nb processors + 1) threads in PROD mode.
+# Try to keep a low as possible. 1 thread will serialize all requests (very useful for debugging purpose)
+# play.pool=3
+
+# Open file from errors pages
+# ~~~~~
+# If your text editor supports opening files by URL, Play! will
+# dynamically link error pages to files
+#
+# Example, for textmate:
+# play.editor=txmt://open?url=file://%s&line=%s
+
+# Testing. Set up a custom configuration for test mode
+# ~~~~~
+#%test.module.cobertura=${play.path}/modules/cobertura
+%test.application.mode=dev
+%test.db.url=jdbc:h2:mem:play;MODE=MYSQL;LOCK_MODE=0
+%test.jpa.ddl=create
+%test.mail.smtp=mock
+
diff --git a/samples-and-tests/i-am-a-developer/tests.py b/samples-and-tests/i-am-a-developer/tests.py
index 1948055825..0d8c9e1f5c 100755
--- a/samples-and-tests/i-am-a-developer/tests.py
+++ b/samples-and-tests/i-am-a-developer/tests.py
@@ -628,6 +628,50 @@ def testSimpleProjectCreation(self):
killPlay()
self.play.wait()
+ def testExternalConfFile(self):
+
+ # Well
+ step('Hello, I need an external application.conf file')
+
+ self.working_directory = bootstrapWorkingDirectory('i-need-an-external-conf-file')
+
+ # play new yop
+ step('Create a new project')
+
+ self.play = callPlay(self, ['new', '%s/externalconffile' % self.working_directory, '--name=EXTCONF'])
+ self.assert_(waitFor(self.play, 'The new application will be created'))
+ self.assert_(waitFor(self.play, 'OK, the application is created'))
+ self.assert_(waitFor(self.play, 'Have fun!'))
+ self.play.wait()
+
+ self.assert_(os.path.exists(os.path.join(self.working_directory, 'externalconffile')))
+ self.assert_(os.path.exists(os.path.join(self.working_directory, 'externalconffile/conf')))
+ self.assert_(os.path.exists(os.path.join(self.working_directory, 'externalconffile/conf/application.conf')))
+
+ app = '%s/externalconffile' % self.working_directory
+
+ # Run the newly created application
+ step('Run the newly created application')
+
+ self.play = callPlay(self, ['run', app])
+ self.assert_(waitFor(self.play, 'Listening for HTTP on port 9000'))
+
+ step("stop play")
+ killPlay()
+ self.play.wait()
+
+ # Run the newly created application
+ step('Run the newly created application with external application.conf file')
+
+ self.play = callPlay(self, ['run', app, '-Dconfig.file=%s/../external-conf-file.conf' % self.working_directory])
+ self.assert_(waitFor(self.play, 'Listening for HTTP on port 9876'))
+
+ step("stop play")
+ killPlay()
+ self.play.wait()
+
+ step("done testing external application.conf file")
+
def tearDown(self):
killPlay()