codeconsole opened a new pull request, #15715:
URL: https://github.com/apache/grails-core/pull/15715

   ## Summary
   
   Adds null-safe, typed conversion methods to the `session`, `request`, 
`flash` and `servletContext` objects, mirroring the existing `params.int('id', 
1)` API. Also adds a missing `string`/`getString` converter to 
`TypeConvertingMap` itself.
   
   ```groovy
   Integer page    = request.int('page', 1)
   String  tz      = session.string('userTimeZoneId', 'America/Los_Angeles')
   Boolean active  = session.boolean('active', false)
   String  notice  = flash.string('notice')
   int     uploads = servletContext.int('maxUploads', 10)
   ```
   
   The full converter set is available — `string`, `byte`, `char`, `short`, 
`int`, `long`, `double`, `float`, `boolean`, `list`, `date` — each with an 
optional default-value overload, exactly as on `params`.
   
   ## Motivation
   
   Under `@CompileStatic` / `@GrailsCompileStatic`, dynamic attribute access 
such as `session.userTimeZoneId` does not compile, and the explicit form 
requires a cast at every call site:
   
   ```groovy
   String tz = (session.getAttribute('userTimeZoneId') as String) ?: 
'America/Los_Angeles'
   ```
   
   These converters give the same null-safe, typed, default-aware ergonomics as 
`params`, and they compile under static compilation. They are equally useful in 
dynamic code for the parsing/defaulting behaviour (just like `params.int(...)`).
   
   ## Design
   
   - Conversion logic is extracted into an internal helper, 
`org.grails.util.TypeConverters`, which converts a raw `Object` value to the 
target type (with an optional default). Both `TypeConvertingMap`'s instance 
`getX` methods and the new attribute extensions delegate to it, so the logic 
lives in a single place and no new conversion methods are added to the public 
`TypeConvertingMap` API.
   - The extensions call the converters directly on the attribute value, 
avoiding any per-access allocation.
   - The instance `getX(name, default)` semantics are preserved, so `params` 
behaviour is unchanged (verified by `GrailsParameterMapBindingSpec`).
   - The one deliberate exception is the `boolean` default: "is the value 
present" differs by holder (map `containsKey` vs. attribute set), which cannot 
be expressed from a value alone, so it stays per-site and is documented inline.
   - The `string` converter returns the first element when the attribute is an 
array, mirroring the single-value semantics of the other converters; use `list` 
for all values.
   
   ## Tests & docs
   
   - Unit tests for the internal converters (incl. default-value coercion) and 
for `getString`/`string`.
   - A Spock spec per holder (`HttpSessionExtensionSpec`, 
`HttpServletRequestExtensionSpec`, `ServletContextExtensionSpec`, 
`FlashScopeExtensionSpec`) covering conversion, null-safety, defaults, and a 
`@CompileStatic` static-resolution guard.
   - `GrailsParameterMapBindingSpec` passes unchanged (regression guard for the 
core refactor).
   - New "Type Conversion of Attributes" section in the controllers guide.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to