jamesfredley commented on issue #15330:
URL: https://github.com/apache/grails-core/issues/15330#issuecomment-3885671270
The Problem
In application.yml (line 35), the configuration is:
```
environments:
development:
serverURL: https://grails7-absolute-link-issue.domain.com
```
The Fix
Change the configuration to one of these patterns:
Option 1: Environment-specific (recommended)
```
environments:
development:
grails:
serverURL: https://grails7-absolute-link-issue.domain.com
```
Option 2: Global setting
```
grails:
serverURL: https://grails7-absolute-link-issue.domain.com
```
The configuration needs to be nested under the `grails:` key, not directly
under `environments.development:`.
The null you're seeing is a race condition in the controller code, not a
configuration problem.
Look at the controller logic:
```
def index() {
String link
Thread.start { // Starts a NEW thread asynchronously
try {
link = grailsLinkGenerator.link(...) // Runs in background
} catch (Exception e) {
e.printStackTrace()
}
}
// Main thread continues immediately without waiting!
String link2 = grailsLinkGenerator.link(...) // Executes in main thread
render link + link2 // Renders BEFORE background thread completes
}
```
What happens:
1. Line 12: Thread starts in background
2. Line 26-31: Main thread immediately generates link2
3. Line 33: render link + link2 executes before the background thread
finishes
4. At this point, link is still null because the thread hasn't completed yet
Updated controller that does not have this issue:
```
package grails7.absolute.link.issue
import grails.web.mapping.LinkGenerator
import java.util.concurrent.Callable
import java.util.concurrent.Executors
import java.util.concurrent.Future
class MakeLinkController {
LinkGenerator grailsLinkGenerator
def index() {
// Use ExecutorService to properly wait for thread completion
def executor = Executors.newSingleThreadExecutor()
try {
// Submit task and get Future
Future<String> future = executor.submit(new Callable<String>() {
@Override
String call() throws Exception {
return grailsLinkGenerator.link(
absolute: true,
controller: 'MakeLink',
action: 'index',
id: 1
)
}
})
// Get result from background thread (waits for completion)
String link = future.get()
// Generate link in web context
String link2 = grailsLinkGenerator.link(
absolute: true,
controller: 'MakeLink',
action: 'index',
id: 1
)
render """
Link from background thread: ${link}
Link from web context: ${link2}
"""
} finally {
executor.shutdown()
}
}
}
```
--
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]