Skip to content

Enable ANSI output on Windows automatically#34835

Closed
ViliusS wants to merge 2 commits into
spring-projects:mainfrom
ViliusS:enable-ansi-on-windows
Closed

Enable ANSI output on Windows automatically#34835
ViliusS wants to merge 2 commits into
spring-projects:mainfrom
ViliusS:enable-ansi-on-windows

Conversation

@ViliusS
Copy link
Copy Markdown
Contributor

@ViliusS ViliusS commented Apr 2, 2023

Windows supports ANSI encoding since Windows 10 version 1909. All you need to do is call ENABLE_VIRTUAL_TERMINAL_PROCESSING when calling console API.

IntelliJ does this automatically.
image
All software running via the new Windows Terminal, including Java, does this as well.
image

Old Windows command prompt doesn't do this by default for compatibility reasons, but new Java versions will make it possible for workaround even for older Windows versions https://stackoverflow.com/questions/74319252/printing-ansi-color-codes-in-java-works-on-vs-code-terminal-but-not-in-cmd

My proposal is to enable ANSI coloring on Windows by default.

Patch should be compatible with both 3.x and 2.7.x branches.

This enables ANSI colored output on IntelliJ running on Windows 10,
or the new Windows Terminal.
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Apr 2, 2023
@snicoll
Copy link
Copy Markdown
Member

snicoll commented Apr 3, 2023

Old Windows command prompt doesn't do this by default for compatibility reasons, but new Java versions will make it possible for workaround even for older Windows versions

Thanks for the PR. Just so that I confirm I understood it, this PR would then break those clients, right? (by returning true instead of checking the windows flag). If so, I don't think we should merge this. Is there a way to check that ENABLE_VIRTUAL_TERMINAL_PROCESSING was set from the Java process?

@snicoll snicoll added the status: waiting-for-feedback We need additional information before we can continue label Apr 3, 2023
@ViliusS
Copy link
Copy Markdown
Contributor Author

ViliusS commented Apr 3, 2023

It won't break, it will just show ANSI symbols in their raw form.

Sadly there is no easy way to check or set Windows API flags in Java process. At least not without using JNI, JNA or similar boilerplate alternative.
As mentioned, JDK 19 preview has SymbolLookup.libraryLookup() implemented which would allow this directly, however even then Java needs to load kernel32.dll library to access Windows API, which is maybe a bit too much just for colors :)

I do not believe stripping Windows IntelliJ or Terminal users from automatic ANSI coloring for those running Spring Boot via old cmd is a great compromise.
If compatibility is such a big issue here, I think applying this to 3.x and mentioning in the Release notes would be enough. Anyone running old console can just disable it via spring.output.ansi.enabled=never

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Apr 3, 2023
@snicoll
Copy link
Copy Markdown
Member

snicoll commented Apr 4, 2023

It won't break, it will just show ANSI symbols in their raw form.

That's what I meant by breaking. Going through a readable log (without colors) to this is certainly a behavioral breaking change.

If compatibility is such a big issue here, I think applying this to 3.x and mentioning in the Release notes would be enough. Anyone running old console can just disable it via spring.output.ansi.enabled=never

Compatibility is important. One can argue that those who can benefit from the improved support could set that exact same property, isn't it?

@snicoll snicoll added status: waiting-for-feedback We need additional information before we can continue and removed status: feedback-provided Feedback has been provided labels Apr 4, 2023
@ViliusS
Copy link
Copy Markdown
Contributor Author

ViliusS commented Apr 4, 2023

I agree. It's probably a matter of what user base is in majority: IntellJ/Eclipse/Windows Terminal users vs Windows cmd users. And not a question of if but when to break compatibility, else innovation stops completely.

In this day and age, I think breaking compatibility in 3.1.x is reasonable.

@spring-projects-issues spring-projects-issues added status: feedback-provided Feedback has been provided and removed status: waiting-for-feedback We need additional information before we can continue labels Apr 4, 2023
@snicoll snicoll added the for: team-attention An issue we'd like other members of the team to review label Apr 4, 2023
@wilkinsona
Copy link
Copy Markdown
Member

IMO, it's too late to make this change in 3.1.x as we don't have enough time to get feedback from the community. I think we should merge it early in 3.2 instead.

@wilkinsona wilkinsona added type: enhancement A general enhancement and removed for: team-attention An issue we'd like other members of the team to review status: waiting-for-triage An issue we've not yet triaged status: feedback-provided Feedback has been provided labels May 2, 2023
@wilkinsona wilkinsona added this to the 3.2.x milestone May 2, 2023
@philwebb
Copy link
Copy Markdown
Member

philwebb commented Jun 2, 2023

I'm not sure that we should merge this one or not. I think it might be quite annoying for those that still use cmd.exe. Perhaps we can take another look at https://github.com/fusesource/jansi which has a Kernel32 class implemented using JNI.

@ViliusS
Copy link
Copy Markdown
Contributor Author

ViliusS commented Jun 2, 2023

I have actually looked at jansi code before, but I could not come up with a working solution. My knowledge of Java is limited :|

If someone could come up with different solution that would be great, however in my opinion loading Kernel32.dll just for this reason is a little bit of waste of resources.

@wilkinsona wilkinsona removed this from the 3.2.x milestone Jun 2, 2023
@wilkinsona wilkinsona added status: waiting-for-triage An issue we've not yet triaged status: pending-design-work Needs design work before any code can be developed for: team-meeting An issue we'd like to discuss as a team to make progress and removed status: pending-design-work Needs design work before any code can be developed labels Jun 2, 2023
@wilkinsona
Copy link
Copy Markdown
Member

wilkinsona commented Jun 21, 2023

Thanks for the suggestion but we have decided that we do not want to merge this change as we feel that the risk of breaking existing users is too high. Those using a shell that supports ansi colouring can add SPRING_OUTPUT_ANSI_ENABLED=always to their environment. Thanks anyway for the PR.

@wilkinsona wilkinsona closed this Jun 21, 2023
@wilkinsona wilkinsona added status: declined A suggestion or change that we don't feel we should currently apply and removed status: waiting-for-triage An issue we've not yet triaged for: team-meeting An issue we'd like to discuss as a team to make progress labels Jun 21, 2023
@ViliusS
Copy link
Copy Markdown
Contributor Author

ViliusS commented Sep 11, 2025

Since Windows 10 is out of support in October, most probably everyone should be using either Windows 10 or Windows 11 right now, and since Spring Boot 4.x is around the corner, can we reconsider this PR?
I can prepare it for latest development branch if needed.

@philwebb philwebb added the for: team-meeting An issue we'd like to discuss as a team to make progress label Sep 11, 2025
@mhalbritter
Copy link
Copy Markdown
Contributor

mhalbritter commented Sep 26, 2025

The PR, as it is, breaks compatibility, because then it will spew ANSI control characters. I've tested with an up-to-date Windows 10 and the findings are:

  • cmd: No color, ANSI control codes printed
  • powershell: No color, ANSI control codes printed
  • Powershell 7: No color, ANSI control codes printed
  • Windows Terminal: Color
  • IntelliJ terminal: Color

To get color working in Cmd and in Powershell 7, the application needs to call the SetConsoleMode Win32 API. This can either be done with JNI, JNA or FFM. All of these options will print a warning when I've tested with Java 25:

WARNING: A restricted method in java.lang.foreign.SymbolLookup has been called
WARNING: java.lang.foreign.SymbolLookup::libraryLookup has been called by org.example.App in an unnamed module (file:/C:/Projects/ansi-test/app/build/classes/java/main/)
WARNING: Use --enable-native-access=ALL-UNNAMED to avoid a warning for callers in this module
WARNING: Restricted methods will be blocked in a future release unless native access is enabled

I assume JANSI has the same problem, as there seems to be no pure Java way to set the console mode on windows.

I don't think having colored output is worth having that warning thrown at the user, and maybe even be blocked in the future, which will either prevent startup or breaking color.

I also don't think enabling it by default is a good default, because Windows Terminal isn't even installed in Windows out of the box, you have to get it from the app store. 3 out of 5 terminals (cmd, powershell, powershell 7) don't work.

In IntelliJ Ultimate, the spring.output.ansi.enabled property is automatically set and the output is in color. In IntelliJ Community, the property isn't set automatically and you get no color by default.

We could maybe detect if we run in a Windows Terminal or find a way to detect if the current terminal is ANSI capable (all of that without invoking native functions), but just blindly enabling it for Windows won't fly.

@mhalbritter
Copy link
Copy Markdown
Contributor

mhalbritter commented Sep 26, 2025

I've also tested a service installation with https://github.com/winsw/winsw, and the log files which are created by winsw (which capture the stdout and stderr from the spring boot app) do not contain ANSI control codes.

@mhalbritter
Copy link
Copy Markdown
Contributor

mhalbritter commented Sep 26, 2025

After testing on Windows 11: Windows Terminal is installed by default and is the standard terminal emulator, meaning even when Win+R "cmd" the cmd process starts in the Windows Terminal, same for PowerShell. And this Windows Terminal supports ANSI color codes out of the box. So maybe enable ANSI by default on Windows 11?

  • cmd: Colors work
  • powershell: Colors work
  • powershell 7: Colors work
  • Windows Terminal: Colors work
  • IntelliJ: Colors work

@philwebb philwebb removed the for: team-meeting An issue we'd like to discuss as a team to make progress label Sep 26, 2025
@ViliusS
Copy link
Copy Markdown
Contributor Author

ViliusS commented Sep 27, 2025

@mhalbritter thank you for the detailed analysis. Just wanted to add, that even on Windows 10, if you start PowerShell or cmd from Windows Terminal they do produce ANSI color output the same way as in Windows 11. Of course, colors when running cmd/PowerShell directly doesn't work as you correctly pointed out.

I do feel that enabling ANSI output by default on Windows 11 could be a good compromise. There still could be people starting Spring Boot services from .cmd/.bat or .ps1 scripts which I believe would skip Windows Terminal and coloring won't work (??), but they should be in a minority and they still have a possibility to disable ANSI via properties.

@mhalbritter
Copy link
Copy Markdown
Contributor

Even .bat/.ps1 files on Windows 11 are started in the Windows terminal and have coloring.

Are you willing to update the PR so that ANSI coloring is enabled for Windows 11, but stays disabled for Windows 10?

@ViliusS
Copy link
Copy Markdown
Contributor Author

ViliusS commented Sep 29, 2025

If such patch would be considered into acceptance, I can adjust it for Windows 11 only. I don't have an extensive Spring Boot dev/testing environment with various Windows and JDK versions, but looking at https://github.com/openjdk/jdk/blob/3d97e17a31c267161c2be87b551cdb118062ff57/src/java.base/windows/native/libjava/java_props_md.c#L467-L551 this should not be too difficult to implement.
The only remaining question is do I do this for newer Windows Server versions too (which I believe also includes Windows Terminal by default), or are we only talking about Windows 11?

@mhalbritter
Copy link
Copy Markdown
Contributor

mhalbritter commented Sep 30, 2025

Unfortunately I don't have access to any modern Windows server versions and I don't know which come with Windows Terminal out of the box, so I think we should only enable it for Windows 11.

@ViliusS
Copy link
Copy Markdown
Contributor Author

ViliusS commented Sep 30, 2025

But in general, if they come with Windows Terminal by default and behave the same way as Windows 11, would you prefer to enable ANSI for Windows Servers? I can test at least 2022 and 2025 versions.

@mhalbritter
Copy link
Copy Markdown
Contributor

If they open the "cmd" in windows terminal and the powershell too, and if cmd/bat files on double click launch in Windows terminal, I don't have a problem with enabling ANSI by default on those systems, too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants