3 設定
Authors: Graeme Rocher, Peter Ledbrook, Marc Palmer, Jeff Brown, Luke Daley, Burt Beckwith ,
Japanese Translation: T.Yamamoto, Japanese Grails Doc Translating Team
このドキュメントの内容はスナップショットバージョンを元に意訳されているため、一部現行バージョンでは未対応の機能もあります。
Version: 2.1.0.BUILD-SNAPSHOT
目次
3 設定
It may seem odd that in a framework that embraces "convention-over-configuration" that we tackle this topic now, but since what configuration there is typically a one-off, it is best to get it out the way.With Grails' default settings you can actually develop an application without doing any configuration whatsoever. Grails ships with an embedded servlet container and in-memory H2 database, so there isn't even a database to set up.However, typically you should configure a more robust database at some point and that is described in the following section.3.1 基本設定
For general configuration Grails provides a file calledgrails-app/conf/Config.groovy
. This file uses Groovy's ConfigSlurper which is very similar to Java properties files except it is pure Groovy hence you can reuse variables and use proper Java types!You can add your own configuration in here, for example:foo.bar.hello = "world"
assert "world" == grailsApplication.config.foo.bar.hello
import org.codehaus.groovy.grails.commons.* … def config = ConfigurationHolder.config assert "world" == config.foo.bar.hello
ConfigurationHolder and ApplicationHolder are deprecated and will be removed in a future version of Grails, so it is highly preferable to access theGrailsApplication
and config from thegrailsApplication
variable.
3.1.1 組込オプション
Grails also provides the following configuration options:grails.config.locations
- The location of properties files or addition Grails Config files that should be merged with main configurationgrails.enable.native2ascii
- Set this to false if you do not require native2ascii conversion of Grails i18n properties filesgrails.views.default.codec
- Sets the default encoding regime for GSPs - can be one of 'none', 'html', or 'base64' (default: 'none'). To reduce risk of XSS attacks, set this to 'html'.grails.views.gsp.encoding
- The file encoding used for GSP source files (default is 'utf-8')grails.mime.file.extensions
- Whether to use the file extension to dictate the mime type in Content Negotiationgrails.mime.types
- A map of supported mime types used for Content Negotiationgrails.serverURL
- A string specifying the server URL portion of absolute links, including server name e.g. grails.serverURL="http://my.yourportal.com". See createLink.
War generation
grails.project.war.file
- Sets the name and location of the WAR file generated by the war commandgrails.war.dependencies
- A closure containing Ant builder syntax or a list of JAR filenames. Lets you customise what libaries are included in the WAR file.grails.war.copyToWebApp
- A closure containing Ant builder syntax that is legal inside an Ant copy, for example "fileset()". Lets you control what gets included in the WAR file from the "web-app" directory.grails.war.resources
- A closure containing Ant builder syntax. Allows the application to do any other other work before building the final WAR file
3.1.2 ロギング
The Basics
Grails uses its common configuration mechanism to provide the settings for the underlying Log4j log system, so all you have to do is add alog4j
setting to the file grails-app/conf/Config.groovy
.So what does this log4j
setting look like? Here's a basic example:log4j = { error 'org.codehaus.groovy.grails.web.servlet', // controllers 'org.codehaus.groovy.grails.web.pages' // GSP warn 'org.apache.catalina' }
Logging levels
The are several standard logging levels, which are listed here in order of descending priority:- off
- fatal
- error
- warn
- info
- debug
- trace
- all
log.error(msg)
will log a message at the 'error' level. Likewise, log.debug(msg)
will log it at 'debug'. Each of the above levels apart from 'off' and 'all' have a corresponding log method of the same name.The logging system uses that message level combined with the configuration for the logger (see next section) to determine whether the message gets written out. For example, if you have an 'org.example.domain' logger configured like so:warn 'org.example.domain'
Loggers
Loggers are fundamental to the logging system, but they are a source of some confusion. For a start, what are they? Are they shared? How do you configure them?A logger is the object you log messages to, so in the calllog.debug(msg)
, log
is a logger instance (of type Log). These loggers are cached and uniquely identified by name, so if two separate classes use loggers with the same name, those loggers are actually the same instance.There are two main ways to get hold of a logger:
- use the
log
instance injected into artifacts such as domain classes, controllers and services; - use the Commons Logging API directly.
log
property, then the name of the logger is 'grails.app.<type>.<className>', where type
is the type of the artifact, for example 'controller' or 'service, and className
is the fully qualified name of the artifact. For example, if you have this service:package org.exampleclass MyService {
…
}
package org.otherimport org.apache.commons.logging.LogFactoryclass MyClass { private static final log = LogFactory.getLog(this) … }
getLog()
method, such as "myLogger", but this is less common because the logging system treats names with dots ('.') in a special way.Configuring loggers
You have already seen how to configure loggers in Grails:log4j = { error 'org.codehaus.groovy.grails.web.servlet' }
org.codehaus.groovy.grails.web.servlet.GrailsDispatcherServlet
class and the org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequest
one.In other words, loggers are hierarchical. This makes configuring them by package much simpler than it would otherwise be.The most common things that you will want to capture log output from are your controllers, services, and other artifacts. Use the convention mentioned earlier to do that: grails.app.<artifactType>.<className> . In particular the class name must be fully qualifed, i.e. with the package if there is one:log4j = { // Set level for all application artifacts info "grails.app" // Set for a specific controller in the default package debug "grails.app.controllers.YourController" // Set for a specific domain class debug "grails.app.domain.org.example.Book" // Set for all taglibs info "grails.app.taglib" }
conf
- For anything undergrails-app/conf
such asBootStrap.groovy
(but excluding filters)filters
- For filterstaglib
- For tag librariesservices
- For service classescontrollers
- For controllersdomain
- For domain entities
org.codehaus.groovy.grails.commons
- Core artifact information such as class loading etc.org.codehaus.groovy.grails.web
- Grails web request processingorg.codehaus.groovy.grails.web.mapping
- URL mapping debuggingorg.codehaus.groovy.grails.plugins
- Log plugin activitygrails.spring
- See what Spring beans Grails and plugins are definingorg.springframework
- See what Spring is doingorg.hibernate
- See what Hibernate is doing
The Root Logger
All logger objects inherit their configuration from the root logger, so if no explicit configuration is provided for a given logger, then any messages that go to that logger are subject to the rules defined for the root logger. In other words, the root logger provides the default configuration for the logging system.Grails automatically configures the root logger to only handle messages at 'error' level and above, and all the messages are directed to the console (stdout for those with a C background). You can customise this behaviour by specifying a 'root' section in your logging configuration like so:log4j = { root { info() } … }
log4j = {
appenders {
file name:'file', file:'/var/logs/mylog.log'
}
root {
debug 'stdout', 'file'
}
}
org.apache.log4j.Logger
instance is passed as an argument to the log4j closure. This lets you work with the logger directly:log4j = { root -> root.level = org.apache.log4j.Level.DEBUG … }
Logger
instance, refer to the Log4j API documentation.Those are the basics of logging pretty well covered and they are sufficient if you're happy to only send log messages to the console. But what if you want to send them to a file? How do you make sure that messages from a particular logger go to a file but not the console? These questions and more will be answered as we look into appenders.Appenders
Loggers are a useful mechanism for filtering messages, but they don't physically write the messages anywhere. That's the job of the appender, of which there are various types. For example, there is the default one that writes messages to the console, another that writes them to a file, and several others. You can even create your own appender implementations!This diagram shows how they fit into the logging pipeline:As you can see, a single logger may have several appenders attached to it. In a standard Grails configuration, the console appender named 'stdout' is attached to all loggers through the default root logger configuration. But that's the only one. Adding more appenders can be done within an 'appenders' block:log4j = { appenders { rollingFile name: "myAppender", maxFileSize: 1024, file: "/tmp/logs/myApp.log" } }
Name | Class | Description |
---|---|---|
jdbc | JDBCAppender | Logs to a JDBC connection. |
console | ConsoleAppender | Logs to the console. |
file | FileAppender | Logs to a single file. |
rollingFile | RollingFileAppender | Logs to rolling files, for example a new file each day. |
name
, maxFileSize
and file
properties of the RollingFileAppender
instance.You can have as many appenders as you like - just make sure that they all have unique names. You can even have multiple instances of the same appender type, for example several file appenders that log to different files.If you prefer to create the appender programmatically or if you want to use an appender implementation that's not available in the above syntax, simply declare an appender
entry with an instance of the appender you want:import org.apache.log4j.*log4j = { appenders { appender new RollingFileAppender( name: "myAppender", maxFileSize: 1024, file: "/tmp/logs/myApp.log") } }
JMSAppender
, SocketAppender
, SMTPAppender
, and more.Once you have declared your extra appenders, you can attach them to specific loggers by passing the name as a key to one of the log level methods from the previous section:error myAppender: "grails.app.controllers.BookController"
error myAppender: "grails.app.controllers.BookController", myFileAppender: ["grails.app.controllers.BookController", "grails.app.services.BookService"], rollingFile: "grails.app.controllers.BookController"
myFileAppender
) by using a list.Be aware that you can only configure a single level for a logger, so if you tried this code:error myAppender: "grails.app.controllers.BookController" debug myFileAppender: "grails.app.controllers.BookController" fatal rollingFile: "grails.app.controllers.BookController"
log4j = {
appenders {
console name: "stdout", threshold: org.apache.log4j.Level.INFO
}
}
threshold
argument which determines the cut-off for log messages. This argument is available for all appenders, but do note that you currently have to specify a Level
instance - a string such as "info" will not work.Custom Layouts
By default the Log4j DSL assumes that you want to use a PatternLayout. However, there are other layouts available including:xml
- Create an XML log filehtml
- Creates an HTML log filesimple
- A simple textual logpattern
- A Pattern layout
layout
setting:log4j = { appenders { console name: "customAppender", layout: pattern(conversionPattern: "%c{2} %m%n") } }
log4j = { appenders { console name: "stdout", layout: pattern(conversionPattern: "%c{2} %m%n") } }
Environment-specific configuration
Since the logging configuration is insideConfig.groovy
, you can put it inside an environment-specific block. However, there is a problem with this approach: you have to provide the full logging configuration each time you define the log4j
setting. In other words, you cannot selectively override parts of the configuration - it's all or nothing.To get around this, the logging DSL provides its own environment blocks that you can put anywhere in the configuration:log4j = { appenders { console name: "stdout", layout: pattern(conversionPattern: "%c{2} %m%n") environments { production { rollingFile name: "myAppender", maxFileSize: 1024, file: "/tmp/logs/myApp.log" } } } root { //… } // other shared config info "grails.app.controller" environments { production { // Override previous setting for 'grails.app.controller' error "grails.app.controllers" } } }
root
definition, but you can put the root
definition inside an environment block.Full stacktraces
When exceptions occur, there can be an awful lot of noise in the stacktrace from Java and Groovy internals. Grails filters these typically irrelevant details and restricts traces to non-core Grails/Groovy class packages.When this happens, the full trace is always logged to theStackTrace
logger, which by default writes its output to a file called stacktrace.log
. As with other loggers though, you can change its behaviour in the configuration. For example if you prefer full stack traces to go to the console, add this entry:error stdout: "StackTrace"
log4j = { appenders { rollingFile name: "stacktrace", maxFileSize: 1024, file: "/var/tmp/logs/myApp-stacktrace.log" } }
log4j = { appenders { 'null' name: "stacktrace" } }
grails.full.stacktrace
VM property to true
:grails -Dgrails.full.stacktrace=true run-app
Masking Request Parameters From Stacktrace Logs
When Grails logs a stacktrace, the log message may include the names and values of all of the request parameters for the current request. To mask out the values of secure request parameters, specify the parameter names in thegrails.exceptionresolver.params.exclude
config property:grails.exceptionresolver.params.exclude = ['password', 'creditCard']
grails.exceptionresolver.logRequestParameters
config property to false
. The default value is true
when the application is running in DEVELOPMENT mode and false
for all other modes.grails.exceptionresolver.logRequestParameters=false
Logger inheritance
Earlier, we mentioned that all loggers inherit from the root logger and that loggers are hierarchical based on '.'-separated terms. What this means is that unless you override a parent setting, a logger retains the level and the appenders configured for that parent. So with this configuration:log4j = {
appenders {
file name:'file', file:'/var/logs/mylog.log'
}
root {
debug 'stdout', 'file'
}
}
log4j = { appenders { … } root { … } info additivity: false stdout: ["grails.app.controllers.BookController", "grails.app.services.BookService"] }
info additivity: false, ["grails.app.controllers.BookController", "grails.app.services.BookService"]
Customizing stack trace printing and filtering
Stacktraces in general and those generated when using Groovy in particular are quite verbose and contain many stack frames that aren't interesting when diagnosing problems. So Grails uses a implementation of theorg.codehaus.groovy.grails.exceptions.StackTraceFilterer
interface to filter out irrelevant stack frames. To customize the approach used for filtering, implement that interface in a class in src/groovy or src/java and register it in Config.groovy
:grails.logging.stackTraceFiltererClass = 'com.yourcompany.yourapp.MyStackTraceFilterer'
org.codehaus.groovy.grails.exceptions.StackTracePrinter
interface in a class in src/groovy or src/java and register it in Config.groovy
:grails.logging.stackTracePrinterClass = 'com.yourcompany.yourapp.MyStackTracePrinter'
org.codehaus.groovy.grails.web.errors.ErrorsViewStackTracePrinter
and it's registered as a Spring bean. To use your own implementation, either implement the org.codehaus.groovy.grails.exceptions.StackTraceFilterer
directly or subclass ErrorsViewStackTracePrinter
and register it in grails-app/conf/spring/resources.groovy
as:import com.yourcompany.yourapp.MyErrorsViewStackTracePrinterbeans = { errorsViewStackTracePrinter(MyErrorsViewStackTracePrinter,
ref('grailsResourceLocator'))
}
Alternative logging libraries
By default, Grails uses Log4J to do its logging. For most people this is absolutely fine, and many users don't even care what logging library is used. But if you're not one of those and want to use an alternative, such as the JDK logging package or logback, you can do so by simply excluding a couple of dependencies from the global set and adding your own:grails.project.dependency.resolution = { inherits("global") { excludes "grails-plugin-logging", "log4j" } … dependencies { runtime "ch.qos.logback:logback-core:0.9.29" … } … }
3.1.3 GORM
Grails provides the following GORM configuration options:grails.gorm.failOnError
- If set totrue
, causes thesave()
method on domain classes to throw agrails.validation.ValidationException
if validation fails during a save. This option may also be assigned a list of Strings representing package names. If the value is a list of Strings then the failOnError behavior will only be applied to domain classes in those packages (including sub-packages). See the save method docs for more information.
grails.gorm.failOnError=true
grails.gorm.failOnError = ['com.companyname.somepackage', 'com.companyname.someotherpackage']
grails.gorm.autoFlush
= If set totrue
, causes the merge, save and delete methods to flush the session, replacing the need to explicitly flush usingsave(flush: true)
.
3.2 環境
Per Environment Configuration
Grails supports the concept of per environment configuration. TheConfig.groovy
, DataSource.groovy
, and BootStrap.groovy
files in the grails-app/conf
directory can use per-environment configuration using the syntax provided by ConfigSlurper As an example consider the following default DataSource
definition provided by Grails:dataSource { pooled = false driverClassName = "org.h2.Driver" username = "sa" password = "" } environments { development { dataSource { dbCreate = "create-drop" url = "jdbc:h2:mem:devDb" } } test { dataSource { dbCreate = "update" url = "jdbc:h2:mem:testDb" } } production { dataSource { dbCreate = "update" url = "jdbc:h2:prodDb" } } }
environments
block specifies per environment settings for the dbCreate
and url
properties of the DataSource
.Packaging and Running for Different Environments
Grails' command line has built in capabilities to execute any command within the context of a specific environment. The format is:grails [environment] [command name]
dev
, prod
, and test
for development
, production
and test
. For example to create a WAR for the test
environment you wound run:grails test war
grails.env
variable to any command:grails -Dgrails.env=UAT run-app
Programmatic Environment Detection
Within your code, such as in a Gant script or a bootstrap class you can detect the environment using the Environment class:import grails.util.Environment...switch (Environment.current) { case Environment.DEVELOPMENT: configureForDevelopment() break case Environment.PRODUCTION: configureForProduction() break }
Per Environment Bootstrapping
Its often desirable to run code when your application starts up on a per-environment basis. To do so you can use thegrails-app/conf/BootStrap.groovy
file's support for per-environment execution:def init = { ServletContext ctx -> environments { production { ctx.setAttribute("env", "prod") } development { ctx.setAttribute("env", "dev") } } ctx.setAttribute("foo", "bar") }
Generic Per Environment Execution
The previousBootStrap
example uses the grails.util.Environment
class internally to execute. You can also use this class yourself to execute your own environment specific logic:Environment.executeForCurrentEnvironment { production { // do something in production } development { // do something only in development } }
3.3 データソース
Since Grails is built on Java technology setting up a data source requires some knowledge of JDBC (the technology that doesn't stand for Java Database Connectivity).If you use a database other than H2 you need a JDBC driver. For example for MySQL you would need Connector/JDrivers typically come in the form of a JAR archive. It's best to use Ivy to resolve the jar if it's available in a Maven repository, for example you could add a dependency for the MySQL driver like this:grails.project.dependency.resolution = { inherits("global") log "warn" repositories { grailsPlugins() grailsHome() grailsCentral() mavenCentral() } dependencies { runtime 'mysql:mysql-connector-java:5.1.16' } }
mavenCentral()
repository is included here since that's a reliable location for this library.If you can't use Ivy then just put the JAR in your project's lib
directory.Once you have the JAR resolved you need to get familiar Grails' DataSource descriptor file located at grails-app/conf/DataSource.groovy
. This file contains the dataSource definition which includes the following settings:
driverClassName
- The class name of the JDBC driverusername
- The username used to establish a JDBC connectionpassword
- The password used to establish a JDBC connectionurl
- The JDBC URL of the databasedbCreate
- Whether to auto-generate the database from the domain model - one of 'create-drop', 'create', 'update' or 'validate'pooled
- Whether to use a pool of connections (defaults to true)logSql
- Enable SQL logging to stdoutformatSql
- Format logged SQLdialect
- A String or Class that represents the Hibernate dialect used to communicate with the database. See the org.hibernate.dialect package for available dialects.readOnly
- Iftrue
makes the DataSource read-only, which results in the connection pool callingsetReadOnly(true)
on eachConnection
properties
- Extra properties to set on the DataSource bean. See the Commons DBCP BasicDataSource documentation.
dataSource { pooled = true dbCreate = "update" url = "jdbc:mysql://localhost/yourDB" driverClassName = "com.mysql.jdbc.Driver" dialect = org.hibernate.dialect.MySQL5InnoDBDialect username = "yourUser" password = "yourPassword" }
When configuring the DataSource do not include the type or the def keyword before any of the configuration settings as Groovy will treat these as local variable definitions and they will not be processed. For example the following is invalid:
dataSource { boolean pooled = true // type declaration results in ignored local variable … }
dataSource { pooled = true dbCreate = "update" url = "jdbc:mysql://localhost/yourDB" driverClassName = "com.mysql.jdbc.Driver" dialect = org.hibernate.dialect.MySQL5InnoDBDialect username = "yourUser" password = "yourPassword" properties { maxActive = 50 maxIdle = 25 minIdle = 5 initialSize = 5 minEvictableIdleTimeMillis = 60000 timeBetweenEvictionRunsMillis = 60000 maxWait = 10000 validationQuery = "/* ping */" } }
More on dbCreate
Hibernate can automatically create the database tables required for your domain model. You have some control over when and how it does this through thedbCreate
property, which can take these values:
- create - Drops the existing schemaCreates the schema on startup, dropping existing tables, indexes, etc. first.
- create-drop - Same as create, but also drops the tables when the application shuts down cleanly.
- update - Creates missing tables and indexes, and updates the current schema without dropping any tables or data. Note that this can't properly handle many schema changes like column renames (you're left with the old column containing the existing data).
- validate - Makes no changes to your database. Compares the configuration with the existing database schema and reports warnings.
- any other value - does nothing
dbCreate
setting completely, which is recommended once your schema is relatively stable and definitely when your application and database are deployed in production. Database changes are then managed through proper migrations, either with SQL scripts or a migration tool like Liquibase (the Database Migration plugin uses Liquibase and is tightly integrated with Grails and GORM).
3.3.1 データソースと環境
The previous example configuration assumes you want the same config for all environments: production, test, development etc.Grails' DataSource definition is "environment aware", however, so you can do:dataSource { pooled = true driverClassName = "com.mysql.jdbc.Driver" dialect = org.hibernate.dialect.MySQL5InnoDBDialect // other common settings here }environments { production { dataSource { url = "jdbc:mysql://liveip.com/liveDb" // other environment-specific settings here } } }
3.3.2 JNDI データソース
Referring to a JNDI DataSource
Most Java EE containers supplyDataSource
instances via Java Naming and Directory Interface (JNDI). Grails supports the definition of JNDI data sources as follows:dataSource {
jndiName = "java:comp/env/myDataSource"
}
DataSource
in Grails remains the same.Configuring a Development time JNDI resource
The way in which you configure JNDI data sources at development time is plugin dependent. Using the Tomcat plugin you can define JNDI resources using thegrails.naming.entries
setting in grails-app/conf/Config.groovy
:grails.naming.entries = [ "bean/MyBeanFactory": [ auth: "Container", type: "com.mycompany.MyBean", factory: "org.apache.naming.factory.BeanFactory", bar: "23" ], "jdbc/EmployeeDB": [ type: "javax.sql.DataSource", //required auth: "Container", // optional description: "Data source for Foo", //optional driverClassName: "org.h2.Driver", url: "jdbc:h2:mem:database", username: "dbusername", password: "dbpassword", maxActive: "8", maxIdle: "4" ], "mail/session": [ type: "javax.mail.Session, auth: "Container", "mail.smtp.host": "localhost" ] ]
3.3.3 自動データベースマイグレーション
ThedbCreate
property of the DataSource
definition is important as it dictates what Grails should do at runtime with regards to automatically generating the database tables from GORM classes. The options are described in the DataSource section:
create
create-drop
update
validate
- no value
dbCreate
is by default set to "create-drop", but at some point in development (and certainly once you go to production) you'll need to stop dropping and re-creating the database every time you start up your server.It's tempting to switch to update
so you retain existing data and only update the schema when your code changes, but Hibernate's update support is very conservative. It won't make any changes that could result in data loss, and doesn't detect renamed columns or tables, so you'll be left with the old one and will also have the new one.Grails supports Rails-style migrations via the Database Migration plugin which can be installed by running
grails install-plugin database-migration
The plugin uses Liquibase and and provides access to all of its functionality, and also has support for GORM (for example generating a change set by comparing your domain classes to a database).
3.3.4 Transaction-awareデータソースプロキシ
The actualdataSource
bean is wrapped in a transaction-aware proxy so you will be given the connection that's being used by the current transaction or Hibernate Session
if one is active.If this were not the case, then retrieving a connection from the dataSource
would be a new connection, and you wouldn't be able to see changes that haven't been committed yet (assuming you have a sensible transaction isolation setting, e.g. READ_COMMITTED
or better).The "real" unproxied dataSource
is still available to you if you need access to it; its bean name is dataSourceUnproxied
.You can access this bean like any other Spring bean, i.e. using dependency injection:class MyService { def dataSourceUnproxied … }
ApplicationContext
:def dataSourceUnproxied = ctx.dataSourceUnproxied
3.3.5 データベースコンソール
The H2 database console is a convenient feature of H2 that provides a web-based interface to any database that you have a JDBC driver for, and it's very useful to view the database you're developing against. It's especially useful when running against an in-memory database.You can access the console by navigating to http://localhost:8080/appname/dbconsole in a browser. The URI can be configured using thegrails.dbconsole.urlRoot
attribute in Config.groovy and defaults to '/dbconsole'
.The console is enabled by default in development mode and can be disabled or enabled in other environments by using the grails.dbconsole.enabled
attribute in Config.groovy. For example you could enable the console in production usingenvironments { production { grails.serverURL = "http://www.changeme.com" grails.dbconsole.enabled = true grails.dbconsole.urlRoot = '/admin/dbconsole' } development { grails.serverURL = "http://localhost:8080/${appName}" } test { grails.serverURL = "http://localhost:8080/${appName}" } }
If you enable the console in production be sure to guard access to it using a trusted security framework.
Configuration
By default the console is configured for an H2 database which will work with the default settings if you haven't configured an external database - you just need to change the JDBC URL tojdbc:h2:mem:devDB
. If you've configured an external database (e.g. MySQL, Oracle, etc.) then you can use the Saved Settings dropdown to choose a settings template and fill in the url and username/password information from your DataSource.groovy.
3.3.6 複数データソース
By default all domain classes share a singleDataSource
and a single database, but you have the option to partition your domain classes into two or more DataSource
s.Configuring Additional DataSources
The defaultDataSource
configuration in grails-app/conf/DataSource.groovy
looks something like this:dataSource { pooled = true driverClassName = "org.h2.Driver" username = "sa" password = "" } hibernate { cache.use_second_level_cache = true cache.use_query_cache = true cache.provider_class = 'net.sf.ehcache.hibernate.EhCacheProvider' }environments { development { dataSource { dbCreate = "create-drop" url = "jdbc:h2:mem:devDb" } } test { dataSource { dbCreate = "update" url = "jdbc:h2:mem:testDb" } } production { dataSource { dbCreate = "update" url = "jdbc:h2:prodDb" } } }
DataSource
with the Spring bean named dataSource
. To configure extra DataSource
s, add another dataSource
block (at the top level, in an environment block, or both, just like the standard DataSource
definition) with a custom name, separated by an underscore. For example, this configuration adds a second DataSource
, using MySQL in the development environment and Oracle in production:environments { development { dataSource { dbCreate = "create-drop" url = "jdbc:h2:mem:devDb" } dataSource_lookup { dialect = org.hibernate.dialect.MySQLInnoDBDialect driverClassName = 'com.mysql.jdbc.Driver' username = 'lookup' password = 'secret' url = 'jdbc:mysql://localhost/lookup' dbCreate = 'update' } } test { dataSource { dbCreate = "update" url = "jdbc:h2:mem:testDb" } } production { dataSource { dbCreate = "update" url = "jdbc:h2:prodDb" } dataSource_lookup { dialect = org.hibernate.dialect.Oracle10gDialect driverClassName = 'oracle.jdbc.driver.OracleDriver' username = 'lookup' password = 'secret' url = 'jdbc:oracle:thin:@localhost:1521:lookup' dbCreate = 'update' } } }
Configuring Domain Classes
If a domain class has noDataSource
configuration, it defaults to the standard 'dataSource'
. Set the datasource
property in the mapping
block to configure a non-default DataSource
. For example, if you want to use the ZipCode
domain to use the 'lookup'
DataSource
, configure it like this;class ZipCode { String code static mapping = { datasource 'lookup' } }
DataSource
s. Use the datasources
property with a list of names to configure more than one, for example:class ZipCode { String code static mapping = { datasources(['lookup', 'auditing']) } }
DataSource
and one or more others, use the special name 'DEFAULT'
to indicate the default DataSource
:class ZipCode { String code static mapping = { datasources(['lookup', 'DEFAULT']) } }
DataSource
s use the special value 'ALL'
:class ZipCode { String code static mapping = { datasource 'ALL' } }
Namespaces and GORM Methods
If a domain class uses more than oneDataSource
then you can use the namespace implied by each DataSource
name to make GORM calls for a particular DataSource
. For example, consider this class which uses two DataSource
s:class ZipCode { String code static mapping = { datasources(['lookup', 'auditing']) } }
DataSource
specified is the default when not using an explicit namespace, so in this case we default to 'lookup'. But you can call GORM methods on the 'auditing' DataSource
with the DataSource
name, for example:def zipCode = ZipCode.auditing.get(42) … zipCode.auditing.save()
DataSource
to the method call in both the static case and the instance case.Hibernate Mapped Domain Classes
You can also partition annotated Java classes into separate datasources. Classes using the default datasource are registered ingrails-app/conf/hibernate/hibernate.cfg.xml
. To specify that an annotated class uses a non-default datasource, create a hibernate.cfg.xml
file for that datasource with the file name prefixed with the datasource name.For example if the Book
class is in the default datasource, you would register that in grails-app/conf/hibernate/hibernate.cfg.xml
:<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC '-//Hibernate/Hibernate Configuration DTD 3.0//EN' 'http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd'> <hibernate-configuration> <session-factory> <mapping class='org.example.Book'/> </session-factory> </hibernate-configuration>
Library
class is in the "ds2" datasource, you would register that in grails-app/conf/hibernate/ds2_hibernate.cfg.xml
:<?xml version='1.0' encoding='UTF-8'?> <!DOCTYPE hibernate-configuration PUBLIC '-//Hibernate/Hibernate Configuration DTD 3.0//EN' 'http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd'> <hibernate-configuration> <session-factory> <mapping class='org.example.Library'/> </session-factory> </hibernate-configuration>
Services
Like Domain classes, by default Services use the defaultDataSource
and PlatformTransactionManager
. To configure a Service to use a different DataSource
, use the static datasource
property, for example:class DataService { static datasource = 'lookup' void someMethod(...) {
…
}
}
DataSource
, so be sure to only make changes for domain classes whose DataSource
is the same as the Service.Note that the datasource specified in a service has no bearing on which datasources are used for domain classes; that's determined by their declared datasources in the domain classes themselves. It's used to declare which transaction manager to use.What you'll see is that if you have a Foo domain class in dataSource1 and a Bar domain class in dataSource2, and WahooService uses dataSource1, a service method that saves a new Foo and a new Bar will only be transactional for Foo since they share the datasource. The transaction won't affect the Bar instance. If you want both to be transactional you'd need to use two services and XA datasources for two-phase commit, e.g. with the Atomikos plugin.XA and Two-phase Commit
Grails has no native support for XADataSource
s or two-phase commit, but the Atomikos plugin makes it easy. See the plugin documentation for the simple changes needed in your DataSource
definitions to reconfigure them as XA DataSource
s.
3.4 設定の外部化
Some deployments require that configuration be sourced from more than one place and be changeable without requiring a rebuild of the application. In order to support deployment scenarios such as these the configuration can be externalized. To do so, point Grails at the locations of the configuration files that should be used by adding agrails.config.locations
setting in Config.groovy
, for example:grails.config.locations = [ "classpath:${appName}-config.properties", "classpath:${appName}-config.groovy", "file:${userHome}/.grails/${appName}-config.properties", "file:${userHome}/.grails/${appName}-config.groovy" ]
USER_HOME
.It is also possible to load config by specifying a class that is a config script.grails.config.locations = [com.my.app.MyConfig]
config
property of the GrailsApplication object and are hence obtainable from there.Values that have the same name as previously defined values will overwrite the existing values, and the pointed to configuration sources are loaded in the order in which they are defined.Config Defaults
The configuration values contained in the locations described by thegrails.config.locations
property will override any values defined in your application Config.groovy
file which may not be what you want. You may want to have a set of default values be be loaded that can be overridden in either your application's Config.groovy
file or in a named config location. For this you can use the grails.config.defaults.locations
property.This property supports the same values as the grails.config.locations
property (i.e. paths to config scripts, property files or classes), but the config described by grails.config.defaults.locations
will be loaded before all other values and can therefore be overridden. Some plugins use this mechanism to supply one or more sets of default configuration that you can choose to include in your application config.Grails also supports the concept of property place holders and property override configurers as defined in Spring For more information on these see the section on Grails and Spring
3.5 バージョニング
Versioning Basics
Grails has built in support for application versioning. The version of the application is set to0.1
when you first create an application with the create-app command. The version is stored in the application meta data file application.properties
in the root of the project.To change the version of your application you can edit the file manually, or run the set-version command:grails set-version 0.2
Detecting Versions at Runtime
You can detect the application version using Grails' support for application metadata using the GrailsApplication class. For example within controllers there is an implicit grailsApplication variable that can be used:def version = grailsApplication.metadata['app.version']
def grailsVersion = grailsApplication.metadata['app.grails.version']
GrailsUtil
class:import grails.util.GrailsUtil
…
def grailsVersion = GrailsUtil.grailsVersion
3.6 プロジェクト・ドキュメント
Since Grails 1.2, the documentation engine that powers the creation of this documentation has been available for your own Grails projects.The documentation engine uses a variation on the Textile syntax to automatically create project documentation with smart linking, formatting etc.Creating project documentation
To use the engine you need to follow a few conventions. First, you need to create asrc/docs/guide
directory where your documentation source files will go. Then, you need to create the source docs themselves. Each chapter should have its own gdoc file as should all numbered sub-sections. You will end up with something like:+ src/docs/guide/introduction.gdoc + src/docs/guide/introduction/changes.gdoc + src/docs/guide/gettingStarted.gdoc + src/docs/guide/configuration.gdoc + src/docs/guide/configuration/build.gdoc + src/docs/guide/configuration/build/controllers.gdoc
src/docs/guide/toc.yml
file that contains the structure and titles for each section. This file is in YAML format and basically represents the structure of the user guide in tree form. For example, the above files could be represented as:introduction: title: Introduction changes: Change Log gettingStarted: Getting Started configuration: title: Configuration build: title: Build Config controllers: Specifying Controllers
title:
plus the title of the section as seen by the end user. Every sub-section then has its own line after the title. Leaf nodes, i.e. those without any sub-sections, declare their title on the same line as the section name but after the colon.That's it. You can easily add, remove, and move sections within the toc.yml
to restructure the generated user guide. You should also make sure that all section names, i.e. the gdoc filenames, should be unique since they are used for creating internal links and for the HTML filenames. Don't worry though, the documentation engine will warn you of duplicate section names.Creating reference items
Reference items appear in the Quick Reference section of the documentation. Each reference item belongs to a category and a category is a directory located in thesrc/docs/ref
directory. For example, suppose you have defined a new controller method called renderPDF
. That belongs to the Controllers
category so you would create a gdoc text file at the following location:+ src/docs/ref/Controllers/renderPDF.gdoc
Configuring Output Properties
There are various properties you can set within yourgrails-app/conf/Config.groovy
file that customize the output of the documentation such as:
- grails.doc.title - The title of the documentation
- grails.doc.subtitle - The subtitle of the documentation
- grails.doc.authors - The authors of the documentation
- grails.doc.license - The license of the software
- grails.doc.copyright - The copyright message to display
- grails.doc.footer - The footer to use
Generating Documentation
Once you have created some documentation (refer to the syntax guide in the next chapter) you can generate an HTML version of the documentation using the command:grails doc
docs/manual/index.html
which can be opened in a browser to view your documentation.Documentation Syntax
As mentioned the syntax is largely similar to Textile or Confluence style wiki markup. The following sections walk you through the syntax basics.Basic Formatting
Monospace:monospace
@monospace@
_italic_
*bold*
!http://grails.org/images/new/grailslogo_topNav.png!
Linking
There are several ways to create links with the documentation generator. A basic external link can either be defined using confluence or textile style markup:[SpringSource|http://www.springsource.com/]
"SpringSource":http://www.springsource.com/
guide:
prefix with the name of the section you want to link to:[Intro|guide:introduction]
[controllers|renderPDF]
api:
prefix. For example:[String|api:java.lang.String]
grails-app/conf/Config.groovy
. For example:grails.doc.api.org.hibernate=
"http://docs.jboss.org/hibernate/stable/core/javadocs"
org.hibernate
package to link to the Hibernate website's API docs.Lists and Headings
Headings can be created by specifying the letter 'h' followed by a number and then a dot:h3.<space>Heading3 h4.<space>Heading4
* item 1 ** subitem 1 ** subitem 2 * item 2
# item 1
table
macro:Name | Number |
---|---|
Albert | 46 |
Wilma | 1348 |
James | 12 |
{table}
*Name* | *Number*
Albert | 46
Wilma | 1348
James | 12
{table}
Code and Notes
You can define code blocks with thecode
macro:class Book {
String title
}
{code}
class Book {
String title
}
{code}
<hello>world</hello>
{code:xml} <hello>world</hello> {code}
This is a note!
{note} This is a note! {note}
This is a warning!
{warning} This is a warning! {warning}
3.7 依存性解決
Grails features a dependency resolution DSL that lets you control how plugins and JAR dependencies are resolved.You specify agrails.project.dependency.resolution
property inside the grails-app/conf/BuildConfig.groovy
file that configures how dependencies are resolved:grails.project.dependency.resolution = { // config here }
grails.project.class.dir = "target/classes" grails.project.test.class.dir = "target/test-classes" grails.project.test.reports.dir = "target/test-reports" //grails.project.war.file = "target/${appName}-${appVersion}.war"grails.project.dependency.resolution = { // inherit Grails' default dependencies inherits("global") { // uncomment to disable ehcache // excludes 'ehcache' } log "warn" repositories { grailsPlugins() grailsHome() grailsCentral() // uncomment these to enable remote dependency resolution // from public Maven repositories //mavenCentral() //mavenLocal() //mavenRepo "http://snapshots.repository.codehaus.org" //mavenRepo "http://repository.codehaus.org" //mavenRepo "http://download.java.net/maven/2/" //mavenRepo "http://repository.jboss.com/maven2/" } dependencies { // specify dependencies here under either 'build', 'compile', // 'runtime', 'test' or 'provided' scopes eg. // runtime 'mysql:mysql-connector-java:5.1.16' } plugins { compile ":hibernate:$grailsVersion" compile ":jquery:1.6.1.1" compile ":resources:1.0" build ":tomcat:$grailsVersion" } }
3.7.1 設定と依存
Grails features five dependency resolution configurations (or 'scopes'):-
build
: Dependencies for the build system only -
compile
: Dependencies for the compile step -
runtime
: Dependencies needed at runtime but not for compilation (see above) -
test
: Dependencies needed for testing but not at runtime (see above) -
provided
: Dependencies needed at development time, but not during WAR deployment
dependencies
block you can specify a dependency that falls into one of these configurations by calling the equivalent method. For example if your application requires the MySQL driver to function at runtime
you can specify that like this:runtime 'com.mysql:mysql-connector-java:5.1.16'
group:name:version
. You can also use a Map-based syntax:runtime group: 'com.mysql', name: 'mysql-connector-java', version: '5.1.16'
group
corresponds to an artifact's groupId
and name
corresponds to its artifactId
.Multiple dependencies can be specified by passing multiple arguments:runtime 'com.mysql:mysql-connector-java:5.1.16', 'net.sf.ehcache:ehcache:1.6.1'// Orruntime( [group:'com.mysql', name:'mysql-connector-java', version:'5.1.16'], [group:'net.sf.ehcache', name:'ehcache', version:'1.6.1'] )
Disabling transitive dependency resolution
By default, Grails will not only get the JARs and plugins that you declare, but it will also get their transitive dependencies. This is usually what you want, but there are occasions where you want a dependency without all its baggage. In such cases, you can disable transitive dependency resolution on a case-by-case basis:runtime('com.mysql:mysql-connector-java:5.1.16', 'net.sf.ehcache:ehcache:1.6.1') { transitive = false }// Or runtime group:'com.mysql', name:'mysql-connector-java', version:'5.1.16', transitive:false
Excluding specific transitive dependencies
A far more common scenario is where you want the transitive dependencies, but some of them cause issues with your own dependencies or are unnecessary. For example, many Apache projects have 'commons-logging' as a transitive dependency, but it shouldn't be included in a Grails project (we use SLF4J). That's where theexcludes
option comes in:runtime('com.mysql:mysql-connector-java:5.1.16', 'net.sf.ehcache:ehcache:1.6.1') { excludes "xml-apis", "commons-logging" }// Or runtime(group:'com.mysql', name:'mysql-connector-java', version:'5.1.16') { excludes([ group: 'xml-apis', name: 'xml-apis'], [ group: 'org.apache.httpcomponents' ], [ name: 'commons-logging' ])
exclude
as well, but that can only accept a single string or Map:runtime('com.mysql:mysql-connector-java:5.1.16',
'net.sf.ehcache:ehcache:1.6.1') {
exclude "xml-apis"
}
Using Ivy module configurations
If you use Ivy module configurations and wish to depend on a specific configuration of a module, you can use thedependencyConfiguration
method to specify the configuration to use.provided("my.org:web-service:1.0") { dependencyConfiguration "api" }
"default"
will be used (which is also the correct value for dependencies coming from Maven style repositories).Where are the JARs?
With all these declarative dependencies, you may wonder where all the JARs end up. They have to go somewhere after all. By default Grails puts them into a directory, called the dependency cache, that resides on your local file system atuser.home
/.grails/ivy-cache. You can change this either via the settings.groovy
file:grails.dependency.cache.dir = "${userHome}/.my-dependency-cache"
grails.project.dependency.resolution = {
…
cacheDir "target/ivy-cache"
…
}
settings.groovy
option applies to all projects, so it's the preferred approach.
3.7.2 依存管理リポジトリ
Remote Repositories
Initially your BuildConfig.groovy does not use any remote public Maven repositories. There is a defaultgrailsHome()
repository that will locate the JAR files Grails needs from your Grails installation. To use a public repository, specify it in the repositories
block:repositories { mavenCentral() }
ebr()
method:repositories { ebr() }
repositories {
mavenRepo "http://repository.codehaus.org"
}
repositories { mavenRepo name: "Codehaus", root: "http://repository.codehaus.org" }
Controlling Repositories Inherited from Plugins
A plugin you have installed may define a reference to a remote repository just as an application can. By default your application will inherit this repository definition when you install the plugin.If you do not wish to inherit repository definitions from plugins then you can disable repository inheritance:repositories {
inherit false
}
Offline Mode
There are times when it is not desirable to connect to any remote repositories (whilst working on the train for example!). In this case you can use theoffline
flag to execute Grails commands and Grails will not connect to any remote repositories:grails --offline run-app
Note that this command will fail if you do not have the necessary dependencies in your local Ivy cacheYou can also globally configure offline mode by setting
grails.offline.mode
to true
in ~/.grails/settings.groovy
or in your project's BuildConfig.groovy
file:grails.offline.mode=true
Local Resolvers
If you do not wish to use a public Maven repository you can specify a flat file repository:repositories { flatDir name:'myRepo', dirs:'/path/to/repo' }
~/.m2/repository
) as a repository:repositories { mavenLocal() }
Custom Resolvers
If all else fails since Grails builds on Apache Ivy you can specify an Ivy resolver:/* * Configure our resolver. */ def libResolver = new org.apache.ivy.plugins.resolver.URLResolver() ['libraries', 'builds'].each { libResolver.addArtifactPattern( "http://my.repository/${it}/" + "[organisation]/[module]/[revision]/[type]s/[artifact].[ext]") libResolver.addIvyPattern( "http://my.repository/${it}/" + "[organisation]/[module]/[revision]/[type]s/[artifact].[ext]") }libResolver.name = "my-repository" libResolver.settings = ivySettingsresolver libResolver
import org.apache.ivy.plugins.resolver.SshResolver … repositories { ... def sshResolver = new SshResolver( name: "myRepo", user: "username", host: "dev.x.com", keyFile: new File("/home/username/.ssh/id_rsa"), m2compatible: true) sshResolver.addArtifactPattern( "/home/grails/repo/[organisation]/[artifact]/" + "[revision]/[artifact]-[revision].[ext]") sshResolver.latestStrategy = new org.apache.ivy.plugins.latest.LatestTimeStrategy() sshResolver.changingPattern = ".*SNAPSHOT" sshResolver.setCheckmodified(true) resolver sshResolver }
grails -classpath /path/to/jsch compile|run-app|etc.
CLASSPATH
environment variable but be aware this it affects many Java applications. An alternative on Unix is to create an alias for grails -classpath ...
so that you don't have to type the extra arguments each time.Authentication
If your repository requires authentication you can configure this using acredentials
block:credentials { realm = ".." host = "localhost" username = "myuser" password = "mypass" }
USER_HOME/.grails/settings.groovy
file using the grails.project.ivy.authentication
setting:grails.project.ivy.authentication = { credentials { realm = ".." host = "localhost" username = "myuser" password = "mypass" } }
3.7.3 依存解決デバッグ
If you are having trouble getting a dependency to resolve you can enable more verbose debugging from the underlying engine using thelog
method:// log level of Ivy resolver, either 'error', 'warn',
// 'info', 'debug' or 'verbose'
log "warn"
grails.project.dependency.resolution = { … log "warn" checksums false … }
3.7.4 依存の受け継ぎ
By default every Grails application inherits several framework dependencies. This is done through the line:inherits "global"
BuildConfig.groovy
file. To exclude specific inherited dependencies you use the excludes
method:inherits("global") { excludes "oscache", "ehcache" }
3.7.5 基本依存管理の提供
Most Grails applications have runtime dependencies on several jar files that are provided by the Grails framework. These include libraries like Spring, Sitemesh, Hibernate etc. When a war file is created, all of these dependencies will be included in it. But, an application may choose to exclude these jar files from the war. This is useful when the jar files will be provided by the container, as would normally be the case if multiple Grails applications are deployed to the same container.The dependency resolution DSL provides a mechanism to express that all of the default dependencies will be provided by the container. This is done by invoking thedefaultDependenciesProvided
method and passing true
as an argument:grails.project.dependency.resolution = { defaultDependenciesProvided true // all of the default dependencies will // be "provided" by the container inherits "global" // inherit Grails' default dependencies repositories { grailsHome() … } dependencies { … } }
defaultDependenciesProvided
must come beforeinherits
, otherwise the Grails dependencies will be included in the war.
3.7.6 依存管理レポート
As mentioned in the previous section a Grails application consists of dependencies inherited from the framework, the plugins installed and the application dependencies itself.To obtain a report of an application's dependencies you can run the dependency-report command:grails dependency-report
target/dependency-report
directory. You can specify which configuration (scope) you want a report for by passing an argument containing the configuration name:grails dependency-report runtime
3.7.7 プラグインJAR依存
Specifying Plugin JAR dependencies
The way in which you specify dependencies for a plugin is identical to how you specify dependencies in an application. When a plugin is installed into an application the application automatically inherits the dependencies of the plugin.To define a dependency that is resolved for use with the plugin but not exported to the application then you can set theexport
property of the dependency:test('org.spockframework:spock-core:0.5-groovy-1.8') {
export = false
}
test group: 'org.spockframework', name: 'spock-core',
version: '0.5-groovy-1.8', export: false
You can useexported = false
instead ofexport = false
, but we recommend the latter because it's consistent with the Map argument.
Overriding Plugin JAR Dependencies in Your Application
If a plugin is using a JAR which conflicts with another plugin, or an application dependency then you can override how a plugin resolves its dependencies inside an application using exclusions. For example:plugins { compile(":hibernate:$grailsVersion") { excludes "javassist" } }dependencies { runtime "javassist:javassist:3.4.GA" }
excludes
method, effectively excluding the javassist library as a dependency.
3.7.8 Maven統合
When using the Grails Maven plugin, Grails' dependency resolution mechanics are disabled as it is assumed that you will manage dependencies with Maven'spom.xml
file.However, if you would like to continue using Grails regular commands like run-app, test-app and so on then you can tell Grails' command line to load dependencies from the Maven pom.xml
file instead.To do so simply add the following line to your BuildConfig.groovy
:grails.project.dependency.resolution = {
pom true
..
}
pom true
tells Grails to parse Maven's pom.xml
and load dependencies from there.
3.7.9 Mavenリポジトリへのデプロイ
If you use Maven to build your Grails project, you can use the standard Maven targetsmvn install
and mvn deploy
.
If not, you can deploy a Grails project or plugin to a Maven repository using the maven-publisher plugin.The plugin provides the ability to publish Grails projects and plugins to local and remote Maven repositories. There are two key additional targets added by the plugin:
- maven-install - Installs a Grails project or plugin into your local Maven cache
- maven-deploy - Deploys a Grails project or plugin to a remote Maven repository
pom.xml
for you unless a pom.xml
is already present in the root of the project, in which case this pom.xml
file will be used.maven-install
Themaven-install
command will install the Grails project or plugin artifact into your local Maven cache:grails maven-install
maven-deploy
Themaven-deploy
command will deploy a Grails project or plugin into a remote Maven repository:grails maven-deploy
<distributionManagement>
configuration within a pom.xml
or that you specify the id
of the remote repository to deploy to:grails maven-deploy --repository=myRepo
repository
argument specifies the 'id' for the repository. Configure the details of the repository specified by this 'id' within your grails-app/conf/BuildConfig.groovy
file or in your $USER_HOME/.grails/settings.groovy
file:grails.project.dependency.distribution = { localRepository = "/path/to/my/local" remoteRepository(id: "myRepo", url: "http://myserver/path/to/repo") }
<remoteRepository id="myRepo" url="scp://localhost/www/repository"> <authentication username="..." privateKey="${user.home}/.ssh/id_dsa"/> </remoteRepository>
remoteRepository(id: "myRepo", url: "scp://localhost/www/repository") { authentication username: "...", privateKey: "${userHome}/.ssh/id_dsa" }
grails maven-deploy --repository=myRepo --protocol=webdav
- http
- scp
- scpexe
- ftp
- webdav
Groups, Artifacts and Versions
Maven defines the notion of a 'groupId', 'artifactId' and a 'version'. This plugin pulls this information from the Grails project conventions or plugin descriptor.Projects
For applications this plugin will use the Grails application name and version provided by Grails when generating thepom.xml
file. To change the version you can run the set-version
command:grails set-version 0.2
groupId
will be the same as the project name, unless you specify a different one in Config.groovy:grails.project.groupId="com.mycompany"
Plugins
With a Grails plugin thegroupId
and version
are taken from the following properties in the *GrailsPlugin.groovy descriptor:String groupId = 'myOrg' String version = '0.1'
FeedsGrailsPlugin
the artifactId
will be "feeds". If your plugin does not specify a groupId
then this defaults to "org.grails.plugins".
3.7.10 プラグイン依存管理
As of Grails 1.3 you can declaratively specify plugins as dependencies via the dependency DSL instead of using the install-plugin command:grails.project.dependency.resolution = { … repositories { … } plugins { runtime ':hibernate:1.2.1' } dependencies { … } … }
org.grails.plugins
is used. You can specify to use the latest version of a particular plugin by using "latest.integration" as the version number:plugins { runtime ':hibernate:latest.integration' }
Integration vs. Release
The "latest.integration" version label will also include resolving snapshot versions. To not include snapshot versions then use the "latest.release" label:plugins { runtime ':hibernate:latest.release' }
The "latest.release" label only works with Maven compatible repositories. If you have a regular SVN-based Grails repository then you should use "latest.integration".And of course if you use a Maven repository with an alternative group id you can specify a group id:
plugins { runtime 'mycompany:hibernate:latest.integration' }
Plugin Exclusions
You can control how plugins transitively resolves both plugin and JAR dependencies using exclusions. For example:plugins {
runtime(':weceem:0.8') {
excludes "searchable"
}
}
excludes
method you can tell Grails not to transitively install the searchable plugin. You can combine this technique to specify an alternative version of a plugin:plugins {
runtime(':weceem:0.8') {
excludes "searchable" // excludes most recent version
}
runtime ':searchable:0.5.4' // specifies a fixed searchable version
}
plugins {
runtime(':weceem:0.8') {
transitive = false
}
runtime ':searchable:0.5.4' // specifies a fixed searchable version
}