Headless Configuration Guide
Overviewโ
Starting with Brobot 1.1.x (September 2025), 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.
For comprehensive configuration options, see the Brobot Properties Usage Guide.
Configurationโ
Setting Headless Modeโ
Headless mode must be explicitly configured via properties:
# application.properties
# Explicitly set headless mode (default: false)
brobot.headless=false
Brobot supports two property paths for headless configuration:
brobot.headless- Flat property path (used byHeadlessDetectorvia@Valueinjection)brobot.core.headless- Nested property path (used inBrobotPropertiesconfiguration)
Both paths reference the same configuration value. Use brobot.headless for simplicity in application.properties.
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:
package io.github.jspinak.brobot.config.environment;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class HeadlessDetector {
private final boolean headlessMode;
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 # Enable mock mode for testing without real UI interactions
- Mock mode (
brobot.mock=true) simulates actions for testing - see Mock Mode Guide - Headless mode (
brobot.headless=true) indicates no display is available - Use both together in CI/CD for complete test environment setup
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=truebefore 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=falsein 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=falseis 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:
package com.example.automation;
import io.github.jspinak.brobot.test.BrobotTestBase;
import io.github.jspinak.brobot.action.Action;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
// In tests, extend BrobotTestBase for headless-safe environment
public class MyTest extends BrobotTestBase {
@Autowired
private Action action;
@Test
public void testMyAutomation() {
// Mock mode is automatically enabled
// Headless-safe testing environment
// Test your automation here
}
}
For comprehensive testing guidance, see:
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:
package com.example.automation;
import io.github.jspinak.brobot.config.environment.HeadlessDetector;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.awt.GraphicsEnvironment;
@Component
public class MyAutomation {
@Autowired
private HeadlessDetector headlessDetector;
public void performAction() {
// Good - uses Brobot's reliable configuration
if (headlessDetector.isHeadless()) {
// Handle headless case
}
// Avoid - unreliable due to caching and platform issues
if (GraphicsEnvironment.isHeadless()) {
// This may give incorrect results
}
}
}
Related Configurationโ
Mock Modeโ
Mock mode (simulated actions) is separate from headless mode:
- Mock mode:
brobot.mock=true- Simulates actions for testing - see Mock Mode Guide - Headless mode:
brobot.headless=true- No display available
Both can be used together for CI/CD testing. When mock mode is enabled, Brobot automatically uses MockScreenCaptureService for screen capture operations.
Screen Captureโ
When running in headless environments, screen capture is typically handled by enabling mock mode:
brobot.headless=true
brobot.mock=true # Automatically uses MockScreenCaptureService
For advanced capture configuration, see the Modular Capture System documentation. Valid capture provider values include: JAVACV_FFMPEG, ROBOT, FFMPEG, SIKULIX, AUTO.
Summaryโ
- Headless mode is explicitly configured via
brobot.headlessproperty - 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
See Alsoโ
Configuration Guidesโ
- Brobot Properties Usage Guide - Complete property reference
- Auto-Configuration Guide - Spring Boot auto-configuration details
- Modular Capture System - Screen capture configuration