Create any SpringBoot project and add a banner.png on the resources folder. Set this as the main application class:

@SpringBootApplication
public class RunSimulators implements ApplicationRunner {
    private static final Logger                   log = LoggerFactory.getLogger(RunSimulators.class);

    /**
     * Method description
     *
     * @param osArgs
     */
    public static void main(String[] osArgs) {
        SpringApplication app = new SpringApplicationBuilder(RunSimulators.class).web(WebApplicationType.NONE)
                                                                                 .headless(false)
                                                                                 .build();

        app.setWebApplicationType(WebApplicationType.NONE);
        app.setHeadless(false);        
        ctx = app.run(osArgs);
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {       
        System.out.println("Headless run: " + String.valueOf(GraphicsEnvironment.isHeadless()));
    }
}

You would expect " Headless run: false ", but you get true. Remove the banner.png file, and now it is false.

Somehow having a banner forces the application to run headless, no matter what we do.

Comment From: wilkinsona

The headless property is set and its previous value reinstated as part of printing the image-based banner:

https://github.com/spring-projects/spring-boot/blob/4eed637481186b0b85bc1cf0b1e77090139477dc/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/ImageBanner.java#L74-L94

Given that SpringApplication already sets the system property, I'm not sure that this is necessary although changing it could break code using ImageBanner outside of SpringApplication.

Comment From: philwebb

I think the problem we have is that we can't actually reset java.awt.headless once a call to GraphicsEnvironment.isHeadless has been called. The GraphicsEnvironment caches the value in a private static Boolean.

When using the ImageBanner, the ImageReader triggers Rectangle.<clinit>() which calls GraphicsEnvironment.isHeadless and sets things in stone.

Thread [main] (Suspended (breakpoint at line 167 in GraphicsEnvironment))   
    GraphicsEnvironment.getHeadlessProperty() line: 167 
    GraphicsEnvironment.isHeadless() line: 145  
    Rectangle.<clinit>() line: 174  
    ImageReader.getDestination(ImageReadParam, Iterator<ImageTypeSpecifier>, int, int) line: 2865   
    GIFImageReader.read(int, ImageReadParam) line: 879  
    ImageBanner.readFrame(int, int, ImageReader, int, ImageReadParam) line: 156 
    ImageBanner.readFrames(int, int, ImageInputStream) line: 145    
    ImageBanner.readFrames(int, int) line: 130  
    ImageBanner.printBanner(Environment, PrintStream) line: 103 
    ImageBanner.printBanner(Environment, Class<?>, PrintStream) line: 79    
    SpringApplicationBannerPrinter$Banners.printBanner(Environment, Class<?>, PrintStream) line: 146    
    SpringApplicationBannerPrinter.print(Environment, Class<?>, PrintStream) line: 72   
    SpringApplication.printBanner(ConfigurableEnvironment) line: 561    
    SpringApplication.run(String...) line: 298  
    DemoApplication.main(String[]) line: 31 

I think our best option is to drop the reset code and only call System.setProperty("java.awt.headless", "true"); if the existing property is null. To only other solution I can think of is to render the image using a new classloader that we then throw away.

Comment From: mhalbritter

We now only set this property if not already set.