grails-core
grails-core copied to clipboard
Problems deploying a Grails 5 war app on Tomcat 10
Issue description
My setup:
- OS: Windwos 10
- Java: jdk-17.0.6
- Grails 5.2.4
- Tomcat 10.1.5 (64-bit Windows zip)
- Eclipse 2022-09 (4.25.0) / IntelliJ 2022.3.2(both IDE I've got the same problems)
- Gradle 7.5
Creating a HelloWorld (a WAR package) application and deploying it ok to webapps folder on tomcat 10.1.5, the first issue I was facing was a 404 error.
Message The requested resource [/TEST01/] is not available
Description The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
Guessing webapps-javaee folder of Tomcat would migrate the app, deployment of the same WAR to webapps-javaee produce a Java.lang.IllegalArgumentException: GrailsVersion snapshot is not in the expected format error.
After that and reading documentation, I can see in Tomcat 10.1.x the Java package used by the specification APIs has changed from javax... to jakarta, so I tried upgrading app dependencies in order to change versions:
- Spring Boot 2.6 to Spring Boot 3
- Spring Framework 5.3 to Spring Framework 6 So in build.gradle:
- org.springframework.boot plugins 3.0.3 version is set up to get Spring Boot 3
- org.grails plugin 6.0.0-M1 version is set up to get Spring Framework 6 In addition I add next dependencies: implementation group: 'jakarta.servlet', name: 'jakarta.servlet-api', version: '6.0.0' implementation 'jakarta.platform:jakarta.jakartaee-web-api:10.0.0' implementation "org.springframework.boot:spring-boot-starter-tomcat:3.0.3" implementation group: 'org.springframework.boot', name: 'spring-boot-starter', version: '3.0.3' implementation group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.14.2' implementation group: 'org.springframework', name: 'spring-web', version: '6.0.6' implementation group: 'org.springframework', name: 'spring-webmvc', version: '6.0.6' implementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core' , version: '10.1.5' implementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-el' , version: '10.1.5' implementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-websocket', version: '10.1.5' implementation group: 'org.apache.tomcat.embed', name: 'tomcat-embed-core' , version: '10.1.5' implementation group: 'org.apache.tomcat' , name: 'tomcat-annotations-api', version: '10.1.5'
Then the app is not able to run in local with grails run-app and can not build the WAR file due to next error: Application.groovy: -1: Can't have an abstract method in a non-abstract class. The class 'test04.ApplicationLoader' must be declared abstract or the method 'void onStartup(jakarta.servlet.ServletContext)' must be implemented.
More deep the error trace shows:
- Exception is: org.gradle.api.tasks.TaskExecutionException: Execution failed for task ':compileGroovy'
Is there any way to get an applications developed in Grails 5 works properly on a Tomcat 10.1.x?
Is there any update on this of how run grails 5 war to tomcat 10?
Is there any update on this of how run grails 5 war to tomcat 10?
In this link, an issue for deployments in tomcat, wildfly, websphere. It seems that grails only works in embedded tomcat: https://github.com/grails/grails-core/issues/12743
As per https://github.com/grails/grails-core/issues/13080 - Grails before version 7 does not support Tomcat 10.
Still waiting on a response for a roadmap for Grails 7.
In general, it's not guaranteed for a normal grails war to work in a Tomcat different to the one that is built into it. Especially major versions, but occasionally minor versions.
What you can do is either:
- specify the tomcat built in, within build.gradle. I forget the exact thing you have to put in there, you'll have to research it, something like Tomcat=10.1 blah, I don't know.
- Build the war without Tomcat built into it. Is that the "plain" war, that the build can generate, or is there a build option to do it that way, I can't remember. I think the plain war, not the tomcat embedded war.
But if you want to make your life easier, keep using tomcat 9 until grails uses something else.
I've tried it - even with a simple Grails application it doesn't work - see issue https://github.com/grails/grails-core/issues/13080
The error being reported seems to be that HibernateDatastoreConnectionSourcesRegistrar is expecting to be able to find a instantiated GrailsVersion instance to decide whether to do some stuff, and one doesn't exist. So its a framework level blocker rather than anything that can be done in the application or by the Tomact10 migration folder
Grails 5 and 6 will never work with Tomcat 10.x. You will need to wait for Grails 7.
Grails <= 6 uses the Servlet 4.x API
In the Servlet 5.x API, the packaging changed from javax.servlet to jakarta.servlet which would make Tomcat 10.x incompatible with Grails. The Servlet 5.x API has no benefit and is just a namespace change.
According to the Tomcat documentation, you need to be running Tomcat 9.x
Why do you wish to run a Grails 5.x app on Tomcat 10.x anyhow? There would be no benefit.
Tomcat 10 has a javaee folder that does a conversion from javax to jakarta namespace for some packages, so I was trying to see if the conversion would work well enough that a Grails app could be converted, and if not whether "enough" was converted that Grails applications of a certain kind would work.
But in my case at least - as documented in https://github.com/grails/grails-core/issues/13080 it fails pretty early on a Grails specific issue that has nothing to do with the javax -> jakarta changes.
The rationale is that Spring 2.x is EOL in November and we are migrating all our Spring apps to Spring 3 in advance of that. That requires Tomcat 10 minimum. We were investigating whether we could run (a migrated) Grails apps on Tomcat 10 so that we could standardize on a single Tomcat version in our stack. The answer appears to be no.
The lack of information Grails running on a supported Spring version (i.e. Grails 7) is becoming a problem at my org. As we have no idea when its going to start being worked on (based on GitHub branch names) , let alone released I suspect we are increasingly going to be challenged to get off the framework by internal policy. Its a shame as we've been a user and supporter of Grails since pre 1.0, and I personally think as a framework it does a great job in the space it occupies at making developers lives easier.
"The lack of information Grails running on a supported Spring version..."
Supported by whom?
"The lack of information Grails running on a supported Spring version..."
Supported by whom?
Spring. Its been our practice to date that if a Grails version is based off a Spring version, then if the Spring point release version is updated by the Spring team and a Grails release is not available that also updates then we update the underlying Spring framework in the application build.gradle by dependency substitution. That's worked well and ensures we can take Spring security updates without being a nuisance to anybody else. Not yet encountered any instances where "going off the Grails reservation" has caused application errors, but I guess its possible.
@boardbloke Spring versions are considered eol when there are no releases in any form. That's 18 months out yet.
https://endoflife.date/spring-boot https://github.com/spring-projects/spring-boot/wiki/Supported-Versions#spring-boot-support-policy
grails, which incorporates spring continues to be supported. Groovy 3.0 isn't supported for a long time by apache, but it didn't bother you. You'd run with a dodgy javaee folder, that isn't supported, if it seemed ok though. Just making the point that rigid policies around these sort of things are kind of silly. If you poke around you'll find tons of stuff in your stack that's "unsupported". Having said that, it would be nice to see some movement on this issue.
Thanks Chris. Maybe I am misreading the policy. Would I correct in saying that OSS support for security fixes in Spring 2.7 ends in 2 months and longer term security fixes are available via commercial support only? I found this https://spring.io/projects/spring-boot#support which seems to say that.
When you say "Grails is supported" what does that mean? If a critical security bug was discovered in Spring 2.x beyond November is it your expectation that the Grails team would look at that because there is no OSS support from Spring, or would you expect further Grails 6.x versions to ship with known Spring vulnerabilities?
In terms of Groovy support - yeah that's an issue for compliance too. The focus on Spring to date has been has been because its a larger framework. That's maybe misplaced.
And the work on Tomcat10 was really just as a POC to see if something could be made to work. I think the better technical solution to taking away the pain of managing multiple Tomcat versions internally is to build fatWars for the Grails components.
Anyway - ultimately I agree with the point you are making. But as I say, there is increasingly internal pressure to have a mitigation plan for potential future security risks. It would be helpful if there was Grails roadmap for Grails 7 - and ideally some sense of whether an upgrade to Boot 3.x by the Feb 2025 date ("proper" Spring 2.7 EOL date) is expected to be "easy" or "challenging".
OSS support supposedly means somebody will look at reported issues on github, and think about them. Commercial support means they'll look at private messages and think about them. In neither case is anybody particularly obliged to do anything. If a security vulnerability of sufficient gravity is reported in the usual places, the owners will presumably fix it for their support contracts. They will check it into github, because it's in nobody's interest to hold back such things. Will they build it, package it up nicely for you as a non-paying customer to consume it? I don't know, my guess is yes problably, because it's in nobody's interest to hold it back, and also because those commercial customer's build processes will want to find those jars in the usual places, and they'll be annoyed if they aren't there.. If they didn't, then the community could package it up. Or you could.
Or in other words, my interpretation of this is, once OSS support ends, don't expect anybody to listen on github, unless it's a critical vulnerability. It's always my assumption anyway that the chances of anybody fixing anything in old versions is basically zero unless it's critical security. Or in other words, I can't see that anything changes once OSS support ends. When commercial support ends, I guess that means nobody at VMware is will be working on the code at all, which is more significant. That's my opinion.
When I say Grails is supported, I mean it in the same sense Spring Boot is supported. You can pay someone to support it. Which is the only real support. So technically, Spring 2.x is still supported, just not by the group you are thinking of. And I would expect if a critical Spring issue came up, somebody in Grails would deal with it, whether you are paying or not. But... it's open source, so unless you are paying, you're relying on somebody else considering your issue as important as you do.
Another way to think about this is nothing is preventing you from upgrading to Spring 3. Anyone can contribute a pull request to Grails, including your organization. Any organization considering migrating off of something should weigh the alternative of simply contributing to what they are running on. You have to evaluate the risks of migrating off of something open source to the possibility of the same thing happening to what you are migrating to.
I suppose my only frustration with the Grails Foundation Technology Advisory Board is the lack of transparency and continued missed milestones. If the founders wouldn't have pulled the ripcord and completely bailed to micronaut, I'd actually have some interest in micronaut, but now I wouldn't even touch micronaut with my mother-in-laws hands. Any new stack for me involves Spring and parts of Grails, but that is just me. I've been burnt one too many times chasing bleeding edge.
I've weighed the consequences of having to migrate off of Grails, and I chose to contribute instead. I ported a very large application to Grails off of another framework that went dead. Porting can be a very large development effort and sometimes it is better to spend that effort getting more acquainted with what you are running on by contributing. My focus now is tearing apart Grails and removing any lock-in with the pieces that I use most.
Fortunately the founders did put some thought into making Grails more modular before they left. There is still a lot of good, useful, intelligent code under the hood. @graemerocher did an amazing job. I suppose most of my animosity here is the my own selfish desire that he kept working on Grails lol.
https://github.com/grails/grails-core/issues/12794