Repository navigation
Error using Warbler to deploy sinatra app into Tomcat #573
Description
JRuby 9.4.x Incompatibility: NoClassDefFoundError: org/jruby/CompatVersion
Summary
WAR files built with Warbler fail to deploy on Apache Tomcat when using JRuby 9.4.x due to a missing org.jruby.CompatVersion class that jruby-rack depends on but was removed in JRuby 9.4.x.
Environment
- JRuby version: 9.4.9.0
- Warbler version: 2.0.5 (gem release) and latest from master branch
- jruby-rack: Bundled by Warbler
- Tomcat version: 9.0.98
- Java version: 21.0.8+9-LTS (Eclipse Adoptium)
Steps to Reproduce
- Create a simple Sinatra application with
config.ru:
require './app'
run Sinatra::Application- Create
Gemfile:
source 'https://rubygems.org'
gem 'sinatra'
gem 'warbler', platforms: :jruby- Create
config/warble.rbwith JRuby 9.3+ workaround:
# Workaround for JRuby 9.3+ new_ostruct_member issue
# See: https://github.com/jruby/warbler/issues/452
class Warbler::Traits::War::WebxmlOpenStruct
def new_ostruct_member(name)
send(:new_ostruct_member!, name)
end
end
Warbler::Config.new do |config|
config.gem_dependencies = true
config.war_name = "hello_world"
config.includes = FileList["app.rb", "config.ru"]
config.bundle_without = []
end- Build WAR file:
jruby -S bundle install
jruby -S bundle exec warble- Deploy to Tomcat and access the application
Expected Behavior
The Sinatra application should start and respond to HTTP requests.
Actual Behavior
The application fails to start with the following error:
java.lang.NoClassDefFoundError: org/jruby/CompatVersion
at java.lang.Class.getDeclaredMethods0(Native Method)
at java.lang.Class.privateGetDeclaredMethods(java/lang/Class)
at java.lang.Class.getDeclaredMethods(java/lang/Class)
at org.jruby.javasupport.binding.MethodGatherer$1.computeValue(org/jruby/javasupport/binding/MethodGatherer.java:300)
...
Caused by: java.lang.ClassNotFoundException: org.jruby.CompatVersion
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1349)
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1158)
Root Cause
The org.jruby.CompatVersion class was removed in JRuby 9.4.x, but jruby-rack (bundled by Warbler) still references this class.
Attempted Workarounds
1. Using Warbler from GitHub master branch
Updated Gemfile to use latest code:
gem 'warbler', git: 'https://github.com/jruby/warbler', branch: 'master', platforms: :jrubyResult: Same error - the GitHub version still bundles a jruby-rack version that expects CompatVersion.
2. Downgrading to JRuby 9.3.x
JRuby 9.3.13.0 still has the CompatVersion class, but it requires Java 21 (class file version 65.0), which creates other compatibility issues with older Tomcat versions.
3. Removing config.webxml.booter
Removed explicit rack booter configuration to let Warbler auto-detect:
# Removed: config.webxml.booter = :rackResult: No change - the error persists.
Additional Context
- The same application works perfectly when run with Trinidad server
- The WAR file builds successfully without errors
- The WAR deploys to Tomcat without errors
- The failure occurs only at runtime when jruby-rack tries to initialize
Related Issues
- 1.x: Avoid removing files not ended in .rb #452 - JRuby 9.3+
new_ostruct_memberissue (resolved with workaround) - This appears to be a new incompatibility introduced in JRuby 9.4.x
Request
Could jruby-rack be updated to be compatible with JRuby 9.4.x, or could Warbler bundle a patched version that doesn't depend on the removed CompatVersion class?
Temporary Solution
Currently, the only workaround is to continue using JRuby 9.3.x or use alternative servers like Trinidad that don't rely on jruby-rack.
Activity
lporras commentedon Oct 4, 2025
I event tried to use
warbler-pre-release-tillscgem, but same error. Tomcat get's up but it does not load the sinatra appchadlwilson commentedon Oct 5, 2025
I think there's some confusion here, which is probably forgiven as the status of warbler is a bit tenuous at the moment, and jruby-rack has only relatively recently been resurrected.
These statements aren't accurate.
https://github.com/jruby/jruby/blob/9.4.14.0/core/src/main/java/org/jruby/CompatVersion.java
jruby-rack 1.1 and 1.2 both work fine on JRuby 9.3 and 9.4, as the compatibility table promises https://github.com/jruby/jruby-rack?tab=readme-ov-file#compatibility
(Unreleased) jruby-rack 1.3 removes the
CompatVersioncoupling. Personally I was in favour of fixing this for jruby-rack 1.2.x because this compatversion functionality is useless on JRuby 9.x - however removing so would technically break the public API onRackConfigso was only done for 1.3 due to this discussion.The GitHub version of Warbler depends on jruby-rack
1.2.x, which will work fine on JRuby 9.3 and 9.4.warbler/warbler.gemspec
Line 34 in 523237b
So what's the problem?
It sounds to me like you are actually accidentally still using JRruby 10 with warbler. Possibly this is because of two things:
warbler/warbler.gemspec
Line 33 in 523237b
1.1or1.2with JRuby 10.This stack trace confirms you are using one of JRuby 10.0.0.0 / 10.0.1.0 / 10.0.2.0, at runtime not 9.4:
https://github.com/jruby/jruby/blob/10.0.2.0/core/src/main/java/org/jruby/javasupport/binding/MethodGatherer.java#L300
Line 300 on JRuby 9.4.9.0 and 9.4.14.0 are different lines so this stack track cannot come from them:
https://github.com/jruby/jruby/blob/9.4.9.0/core/src/main/java/org/jruby/javasupport/binding/MethodGatherer.java#L300
https://github.com/jruby/jruby/blob/9.4.14.0/core/src/main/java/org/jruby/javasupport/binding/MethodGatherer.java#L300
This is probably why you got confused and thought downgrading to JRuby 9.3 required Java 21. You probably downgraded your shell version, but still bundled
jruby-jars10.x.So what's the problem?
Double check you are actually running with JRuby 9.4.x. You may believe you are based on your command line installed JRuby version because you have it installed when running warbler, but warbler has not actually bundled JRuby 9.4.x into your war file.
You can try the example at https://github.com/jruby/jruby-rack/tree/master/examples/sinatra ? I updated this recently and it was working fine with Tomcat 9, jruby-rack 1.2.x, jruby 9.4.x
In practice I think I needed to use
warbler-pre-release-tillscgem to workaround some of the bundler/Gem.pathissues with using warbler off master, but wasn't comfortable committing the example as such - was hoping for a warbler fix/release.Avoiding this?
Either the gemspec for warbler OR the jruby-rack versions should really impose a constraint on the jruby-jars version to avoid this. Unfortunately can't fix that for historic jruby-rack versions so the best place to address this would still be in warbler.
lporras commentedon Oct 8, 2025
@chadlwilson thanks for your response. so I'm using docker for this project and I tried to use jruby 9.3.13.0 with java 17, but same problem tomcat server is up but i does not load my sinatra app.
Here is my dockerfile:
with docker-compose.yml:
I'm also getting this comment from Claude Code:
I see - you changed it to openjdk:17-slim but you're downloading JRuby 9.3.13.0 binaries from Maven Central at line 6. Those pre-built JRuby binaries were compiled with Java 21, regardless of what Java version you have in your container. The issue is that the JRuby distribution itself (the tar.gz file you download) contains JARs compiled with Java 21. When Warbler packages your WAR, it includes those JRuby JARs. You have two options:
Use Java 21 to match the JRuby binaries
Use an older JRuby version that was compiled with Java 17 or earlier (like JRuby 9.3.10.0 or earlier)
Let me check which JRuby versions support Java 17:
lporras commentedon Oct 8, 2025
@chadlwilson I changed to use openjdk:21-slim instead, and i was able to run my sinatra app on tomcat 9 using warble and jruby 9.3.13.0
chadlwilson commentedon Oct 8, 2025
Claude code is telling you lies.
JRuby 9.3 came out in 2021, 2 years before Java 21 - so that doesn't make any sense whatsoever. Java 9.3 and 9.4 minimum Java version is Java 8, not 21.
I don't have your Gemfile so can't replicate your docker build, but if you build with
docker build . --progress=plainyou will probably find thatbundle installis installingjruby-jars=10.0.2.0, that v10 is locked insideGemfile.lockand that the war file actually built contains jruby 10 - not 9.3/9.4.e.g with
you get
Fetching jruby-rack 1.2.5
Fetching rack 2.2.19
Fetching jruby-jars 10.0.2.0
I'd be very surprised if your app above works properly if it is installing jruby 10, as jruby-rack doesn't work with Jruby 10, but in any case, I would suggest you add to your Gemfile
gem 'jruby-jars', '< 10'to ensure it does not, since this is not a tested/valid/supported combination.chadlwilson commentedon Oct 11, 2025
I've looked into this a bit more and warbler will likely work ok with JRuby 10 and jruby-rack 1.2.5 as long as
3).you don't do any special jruby-rack stuff with the
RackConfig(unlikely if using Sinatra)There is only one known incompatibility from a removed class in JRuby 10 which is not always invoked/needed. It's most commonly a problem when debugging rack initialization failures as the original failure will be replaced by a ClassNotFoundError.
I'll look to back-port a fix for these issues above to jruby-rack 1.2.6 to avoid this being a risk and make it a supported combination.
TL;DR - if anyonecs JRuby 10 setup is working ok on Tomcat 9 with Java 21 they can probably safely continue, and it'll get even safer with jruby-rack 1.2.6. Many folks will current be having initialization issues due to bugs needing a release in warbler 2.1.0, which will be causing the rack initialization to fail (and may then cause this downstream issue on JRuby 10)