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.