Headless Configuration Guide
Overviewโ
Starting with Brobot 1.1.0, headless mode is explicitly configured via properties rather than auto-detected. This simplifies the codebase and avoids issues with Java's unreliable GraphicsEnvironment.isHeadless()
detection, particularly on Windows systems.
Configurationโ
Setting Headless Modeโ
Headless mode must be explicitly configured via properties:
# application.properties
# Explicitly set headless mode (default: false)
brobot.headless=false
Property Valuesโ
Value | Description | Use Case |
---|---|---|
false (default) | GUI is available | Normal desktop environments, Windows/Mac/Linux with displays |
true | No display available | CI/CD pipelines, headless servers, Docker containers, test environments |
How It Worksโ
Simple Configuration-Based Approachโ
The HeadlessDetector
component simply reads the configured property value:
@Component
public class HeadlessDetector {
public HeadlessDetector(@Value("${brobot.headless:false}") boolean brobotHeadless) {
// Uses configured value ONLY - no auto-detection
this.headlessMode = brobotHeadless;
}
public boolean isHeadless() {
return headlessMode; // Returns configured value
}
}
No More Complex Workaroundsโ
Previous versions attempted various workarounds for headless detection issues. These have been removed in favor of the simpler approach:
- โ Removed:
ForceNonHeadlessInitializer
- โ Removed:
RobotForcedInitializer
- โ Removed: Direct Robot manipulation
- โ Kept: Simple property-based configuration
Common Scenariosโ
Desktop Development (Windows/Mac/Linux)โ
# Default configuration - no changes needed
# brobot.headless defaults to false
CI/CD Pipeline (GitHub Actions, Jenkins)โ
# application-ci.properties
brobot.headless=true
brobot.mock=true # Also enable mock mode for testing
Docker Containerโ
# application-docker.properties
brobot.headless=true
brobot.mock=true
WSL2 Developmentโ
# WSL2 with WSLg (GUI support)
brobot.headless=false
# WSL2 without display
brobot.headless=true
Why We Changedโ
The Problem with Auto-Detectionโ
Java's GraphicsEnvironment.isHeadless()
has several issues:
- Cached Results: Once called, the result is cached and cannot change
- Gradle Interference: Gradle often sets
java.awt.headless=true
before the JVM starts - Timing Issues: Early initialization can lock in the wrong headless state
- Platform Inconsistency: Different behavior on different operating systems
The Solution: Explicit Configurationโ
By using explicit configuration:
- Predictable: You know exactly what mode you're in
- Simple: No complex detection logic or workarounds
- Reliable: Works consistently across all platforms
- Testable: Easy to test both modes
Troubleshootingโ
Issue: Getting HeadlessExceptionโ
Symptom: HeadlessException
when running automation
Solution:
- Ensure
brobot.headless=false
in your properties - If using Gradle, add to
gradle.properties
:org.gradle.jvmargs=-Djava.awt.headless=false
Issue: Click Actions Not Workingโ
Symptom: Images are found but clicks fail
Solution:
- This is likely a headless detection issue
- Ensure
brobot.headless=false
is set - The click action now uses SikuliX directly, which handles Robot initialization lazily
Issue: Different Behavior in Testsโ
Symptom: Tests behave differently than production
Solution: Ensure consistent configuration:
// In tests, extend BrobotTestBase
public class MyTest extends BrobotTestBase {
// Mock mode is automatically enabled
// Headless-safe testing environment
}
Best Practicesโ
-
Always set explicitly for production: Don't rely on defaults
brobot.headless=false # Explicitly set for your environment
-
Use profiles for different environments:
# application-dev.properties
brobot.headless=false
# application-ci.properties
brobot.headless=true -
Use HeadlessDetector, not GraphicsEnvironment:
// Good
@Autowired
private HeadlessDetector headlessDetector;
if (headlessDetector.isHeadless()) { }
// Avoid - unreliable
if (GraphicsEnvironment.isHeadless()) { }
Related Configurationโ
Mock Modeโ
Mock mode (simulated actions) is separate from headless mode:
- Mock mode:
brobot.mock=true
- Simulates actions for testing - Headless mode:
brobot.headless=true
- No display available
Both can be used together for CI/CD testing.
Screen Captureโ
When brobot.headless=true
, ensure appropriate capture provider:
brobot.capture.provider=MOCK # Use mock provider for headless
Summaryโ
- Headless mode is explicitly configured via
brobot.headless
property - Auto-detection has been removed for simplicity and reliability
- Default is
false
(assumes display is available) - No more complex workarounds or Robot initialization tricks
- SikuliX handles all low-level details automatically