# message

## Purpose

Resolves a message from the given code or error. Normally used in conjunction with eachError. O

## Examples

Loop through each error and output the message:

    <g:eachError bean="${book}">
        <li><g:message error="${it}" /></li>
    </g:eachError>

> Note that this is typically used for built-in Grails messages, rather than user application messages. For user application messages, use the code or message parameters, as illustrated below.

Output a message for a specific known code:

    <g:message code="my.message.code" />

Output a message for a compatible object.

    <g:message message="${myObj}" />

> Note that objects passed to the message parameter must implement the org.springframework.context.MessageSourceResolvable interface.

## Description

Attributes

- `error` (optional) - The error to resolve the message for. Used for built-in Grails messages.
- `code` (optional) - The code to resolve the message for. Used for custom application messages.
- `message` (optional) - The object to resolve the message for. Objects must implement org.springframework.context.MessageSourceResolvable.
- `default` (optional) - The default message to output if the error or code cannot be found in messages.properties.
- `args` (optional) - A list of argument values to apply to the message, when code is used.
- `encodeAs` (optional - 0.6+) - The name of a codec to apply, i.e. HTML, JavaScript, URL etc

One of either the `error` attribute, the `code` attribute or the `message` attribute is required. Messages are resolved from the `grails-app/i18n/messages.properties` bundle. See also Internationalization.

For a more complex example, to output your own message with parameters and a default message, you might use the following code from your controller:

    flash.message = "book.delete.message"
    flash.args = [ "The Stand" ]
    flash.default = "book deleted"

You would then specify the following in messages.properties:

    book.delete.message="Book {0} deleted."

and specify the following from your view:

    <g:message code="${flash.message}" args="${flash.args}" default="${flash.default}"/>

Which would result in the output "Book The Stand deleted." If you had misnamed the message or not specified it in `messages.properties`, your default message of "book deleted" would be output.

## Source

Show Source

    def message = { attrs ->
        	messageImpl(attrs)
        }
        def messageImpl(attrs) {
            def messageSource = grailsAttributes.getApplicationContext().getBean("messageSource")
              def locale = attrs.locale ?: RCU.getLocale(request)          def text
              def error = attrs['error'] ?: attrs['message']
              if(error) {
                    try {
                    	text = messageSource.getMessage( error , locale )
                    } catch (NoSuchMessageException e) {
                    	if(error instanceof MessageSourceResolvable) {
                    		text = error?.code
                    	} else {
                    		text = error?.toString()
                    	}
                    }
              } else if(attrs['code']) {
                    def code = attrs['code']
                    def args = attrs['args']
                    def defaultMessage = ( attrs['default'] != null ? attrs['default'] : code )                def message = messageSource.getMessage( code,
                                                            args == null ? null : args.toArray(),
                                                            defaultMessage,
                                                            locale )
                    if(message != null) {
                        text = message
                    }
                    else {
                        text = defaultMessage
                    }
              }
              if (text) {
                    return (attrs.encodeAs ? text."encodeAs${attrs.encodeAs}"() : text)
              }
              return ''
        }    // Maps out how Grails contraints map to Apache commons validators
        static CONSTRAINT_TYPE_MAP = [ email : 'email',
                                                 creditCard : 'creditCard',
                                                 match : 'mask',
                                                 blank: 'required',
                                                 nullable: 'required',
                                                 maxSize: 'maxLength',
                                                 minSize: 'minLength',
                                                 range: 'intRange',
                                                 size: 'intRange',
                                                 length: 'maxLength,minLength' ]