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()