Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Breaking change in ResponseEntity.getStatusCode() breaks lots of code #31600

Closed
Ed42 opened this issue Nov 14, 2023 · 5 comments
Closed

Breaking change in ResponseEntity.getStatusCode() breaks lots of code #31600

Ed42 opened this issue Nov 14, 2023 · 5 comments
Labels
status: invalid An issue that we don't feel is valid

Comments

@Ed42
Copy link

Ed42 commented Nov 14, 2023

Affects:
Spring Framework 6.0.13

The change to ResponseEntity.getStatusCode() returning the HttpStatusCode interface instead of the HttpStatus implementation breaks all callers that were expecting HttpStatus returns.

Example error:

java.lang.NoSuchMethodError: 'org.springframework.http.HttpStatus org.springframework.http.ResponseEntity.getStatusCode()'

This break in backwards-compatibility has greatly impacted our migration to Spring Boot 3.x

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Nov 14, 2023
@bclozel
Copy link
Member

bclozel commented Nov 14, 2023

Thanks for your feedback @Ed42 - this change was introduced in #28214. We realize this change is not transparent and this is why this was introduced in a major version. As you can see in the issue description, we took extra steps to minimize disruption in applications.

Unfortunately, we cannot change this arrangement at this stage. We would love to get this feedback during the milestone phases.

There is already a note in the upgrade wiki on HttpMethod but not for this one. I guess this involved changing HttpStatus assignments to HttpStatusCode in your code? If you can explain more about the impact during the upgrade, maybe we can improve the wiki to help others. Still, I'm closing this issue now as there's nothing actionable in the project.

Thanks!

@bclozel bclozel closed this as not planned Won't fix, can't repro, duplicate, stale Nov 14, 2023
@bclozel bclozel added status: invalid An issue that we don't feel is valid and removed status: waiting-for-triage An issue we've not yet triaged or decided on labels Nov 14, 2023
@Ed42
Copy link
Author

Ed42 commented Nov 14, 2023

In Spring 5.x the HttpStatus is an enum that does not implement any interfaces. In 6.x the same enum implements interface HttpStatusCode, and it is this interface that is now returned by ResponseEntity.getStatusCode(). This means there is no way to maintain a single piece of code that is compatible with both Spring major release versions. Company policy beyond my control precludes the use of milestone releases.

Such a breaking change is a poor choice without some mechanism for backwards compatibility, as this means we now have to maintain two versions of the same code while we are transitioning to Spring Boot 3.x, Spring 6.x.
This project I'm working on has many Spring libraries, some of which are over 12 years old and have all worked perfectly for years. If they now start breaking unpredictably, even if the underlying reason has good rationale, this will complicate things enormously.

@bclozel
Copy link
Member

bclozel commented Nov 15, 2023

This means there is no way to maintain a single piece of code that is compatible with both Spring major release versions.

I think this is unrealistic expectations. Spring Framework 5 and 6 have very different baselines: JDK8 vs JDK17, Javax vs Jakarta, etc. For a Spring dependent library, I would assume a major version in sync with the baseline requirements of Spring itself.

Company policy beyond my control precludes the use of milestone releases.

I'm not suggesting usage of milestone versions in production, but rather testing milestone versions locally with existing applications to prepare future upgrades and send timely feedback to the team. Without this, you're effectively relying on the rest of the community to do that work for you. In this case, we had no complaints about this for 1.5 year and at this point it's too late to make any significant change about that.

Such a breaking change is a poor choice without some mechanism for backwards compatibility, as this means we now have to maintain two versions of the same code while we are transitioning to Spring Boot 3.x, Spring 6.x.
This project I'm working on has many Spring libraries, some of which are over 12 years old and have all worked perfectly for years. If they now start breaking unpredictably, even if the underlying reason has good rationale, this will complicate things enormously.

I'm sorry this is making things more complicated for you, we're always trying to provide the best upgrade experience to the community. Still, I'm not sure it's fair to expect your library to be compatible with two major generations of Spring. There is no Spring project that does this in our entire portfolio for this very reason. If we cannot make any breaking change in major versions, there is simply no other way to make them and move the project forward.

Thanks for your feedback!

@CharlieReitzel
Copy link

CharlieReitzel commented Nov 17, 2023

Still not clear on the compelling use case that justifies breaking so much code. How, specifically, does breaking ResponseEntity "move the project forward"?

The way #28214 is written, it appears to be a theoretical concern. Are there any practical benefits to this change? Or is just another pedantic change foisted on 1000s of projects for academic reasons? Java developers already have a bad reputation. This just adds fuel to the fire ... :--)

@ae-govau
Copy link

To add another data point, this change also broke us, not at compile time, but at runtime after deploying to an env. We depend on another library which depended on this, and now we need to go and find the maintainers of that other library, get them to re-write their code, publish a new version, then push a new version of our code.

I realise that transitive library dependency is impossible to solve fully, but it can be mitigated significantly by being prudent about the types of breaking changes that imposed on users of a library.

I'd argue in this case the same goal could have been met by adding a new method getExtendedHttpStatusCode() or similar and deprecating the previous one, and without unnecessarily breaking all the dependent projects.

I realise it's too late this roll this one back, but I hope feedback like this is collected and used to inform future changes by the Spring teams.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: invalid An issue that we don't feel is valid
Projects
None yet
Development

No branches or pull requests

5 participants