From 48b0be8e27adf4a6fa05ecdcf79a5b7c5e1a20ed Mon Sep 17 00:00:00 2001 From: Chad Wilson <29788154+chadlwilson@users.noreply.github.com> Date: Fri, 17 Apr 2026 17:13:59 +0800 Subject: [PATCH 1/6] [build] Prefer compile against jruby-complete due to bundler-maven-plugin quirks We only need the deconstructed variant, but bundler-maven-plugin has a quirk where it only filters jruby-complete from forked process which we need to compile targetting one JRuby version, but run tests on another. --- pom.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 2bd5b72e..66d97270 100644 --- a/pom.xml +++ b/pom.xml @@ -76,7 +76,9 @@ org.jruby - jruby + + jruby-complete ${jruby.version} provided From 030159f5d8fb04fc2ffd2f207a1afc333b54b18c Mon Sep 17 00:00:00 2001 From: Chad Wilson <29788154+chadlwilson@users.noreply.github.com> Date: Fri, 17 Apr 2026 17:15:51 +0800 Subject: [PATCH 2/6] [test] Tidy specs to avoid requiring things until later This makes it much easier to debug issues with requires, since they then don't affect every single test. --- src/spec/ruby/rack/config_spec.rb | 4 ++-- src/spec/ruby/spec_helper.rb | 19 +++++++------------ 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/spec/ruby/rack/config_spec.rb b/src/spec/ruby/rack/config_spec.rb index 452165b5..6eb2d85a 100644 --- a/src/spec/ruby/rack/config_spec.rb +++ b/src/spec/ruby/rack/config_spec.rb @@ -1,6 +1,6 @@ require File.expand_path('spec_helper', File.dirname(__FILE__) + '/..') -describe org.jruby.rack.DefaultRackConfig do +describe 'org.jruby.rack.DefaultRackConfig' do let(:config) do config = org.jruby.rack.DefaultRackConfig.new @@ -23,7 +23,7 @@ end -describe org.jruby.rack.servlet.ServletRackConfig do +describe 'org.jruby.rack.servlet.ServletRackConfig' do let(:config) do config = org.jruby.rack.servlet.ServletRackConfig.new(@servlet_context) diff --git a/src/spec/ruby/spec_helper.rb b/src/spec/ruby/spec_helper.rb index 7af5be90..d3ccae07 100644 --- a/src/spec/ruby/spec_helper.rb +++ b/src/spec/ruby/spec_helper.rb @@ -22,16 +22,10 @@ module SharedHelpers - java_import 'org.jruby.rack.RackContext' - java_import 'org.jruby.rack.RackConfig' - java_import 'org.jruby.rack.servlet.ServletRackContext' - java_import 'javax.servlet.ServletContext' - java_import 'javax.servlet.ServletConfig' - def mock_servlet_context - @servlet_context = ServletContext.impl {} - @rack_config ||= RackConfig.impl {} - @rack_context ||= ServletRackContext.impl {} + @servlet_context = Java::JavaxServlet::ServletContext.impl {} + @rack_config ||= Java::OrgJrubyRack::RackConfig.impl {} + @rack_context ||= Java::OrgJrubyRackServlet::ServletRackContext.impl {} [@rack_context, @servlet_context].each do |context| allow(context).to receive(:log) allow(context).to receive(:isEnabled).and_return nil @@ -39,9 +33,10 @@ def mock_servlet_context allow(context).to receive(:getRealPath).and_return "/" allow(context).to receive(:getResource).and_return nil allow(context).to receive(:getContextPath).and_return "/" + allow(context).to receive(:init_parameter_names).and_return [] end allow(@rack_context).to receive(:getConfig).and_return @rack_config - @servlet_config ||= ServletConfig.impl {} + @servlet_config ||= Java::JavaxServlet::ServletConfig.impl {} allow(@servlet_config).to receive(:getServletName).and_return "a Servlet" allow(@servlet_config).to receive(:getServletContext).and_return @servlet_context @servlet_context @@ -151,8 +146,8 @@ def should_eval_as_not_nil(code) config.backtrace_exclusion_patterns = [ /bin\//, - #/gems/, - /spec\/spec_helper\.rb/, + # /gems/, + # /spec\/spec_helper\.rb/, ] end From 915e375b2823e06d8d40c9184bb14ea480e5c6cf Mon Sep 17 00:00:00 2001 From: Chad Wilson <29788154+chadlwilson@users.noreply.github.com> Date: Fri, 17 Apr 2026 17:19:37 +0800 Subject: [PATCH 3/6] [fix] Ensure all Throwables occurring during exception metadata capture are handled While this shouldn't happen, currently if it does, the root exception is lost, which can be catastrophic for debugging. --- .../rack/DefaultRackApplicationFactory.java | 2 +- src/spec/ruby/rack/application_spec.rb | 34 +++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/jruby/rack/DefaultRackApplicationFactory.java b/src/main/java/org/jruby/rack/DefaultRackApplicationFactory.java index c0bcec14..0b4c6ba4 100644 --- a/src/main/java/org/jruby/rack/DefaultRackApplicationFactory.java +++ b/src/main/java/org/jruby/rack/DefaultRackApplicationFactory.java @@ -439,7 +439,7 @@ private void captureMessage(final RaiseException re) { rubyException.callMethod(context, "capture"); rubyException.callMethod(context, "store"); } - catch (Exception e) { + catch (Throwable e) { rackContext.log(INFO, "failed to capture exception message", e); // won't be able to capture anything } diff --git a/src/spec/ruby/rack/application_spec.rb b/src/spec/ruby/rack/application_spec.rb index 1a2852f8..973d7a19 100644 --- a/src/spec/ruby/rack/application_spec.rb +++ b/src/spec/ruby/rack/application_spec.rb @@ -476,6 +476,40 @@ def reset_config expect(e.message).to eql 'something went wrong' end end + + it "swallows and logs errors during exception detail capturing" do + expect(@rack_config).to receive(:getRackup).and_return("raise 'something went wrong'") + expect_any_instance_of(Exception).to receive(:capture).and_raise java.lang.NoClassDefFoundError.new("missing class during exception capture") + + app_factory = mocked_runtime_application_factory + app_factory.init @rack_context + app_object = app_factory.newApplication + + raise_info_logged = 0 + raise_error_logged = 0 + allow(@rack_context).to receive(:log) do |level, msg, e| + if level.to_s == 'INFO' + expect(msg).to eql 'failed to capture exception message' + expect(e).to be_a java.lang.NoClassDefFoundError + raise_info_logged += 1 + elsif level.to_s == 'ERROR' + expect(msg).to eql 'unable to initialize application' + expect(e).to be_a org.jruby.exceptions.RaiseException + raise_error_logged += 1 + else + true + end + end + + begin + app_object.init + fail "expected to raise" + rescue => e + expect(e.message).to eql 'something went wrong' + end + + expect(raise_info_logged).to eql 1 # logs info message for exception capture + end end describe "getApplication" do From e7b349e3eb0961d38733ab7227960a6c9a076ef8 Mon Sep 17 00:00:00 2001 From: Chad Wilson <29788154+chadlwilson@users.noreply.github.com> Date: Fri, 17 Apr 2026 17:21:38 +0800 Subject: [PATCH 4/6] [build] always compile against default jruby; but run tests with designated version --- .github/workflows/maven.yml | 5 ++--- Rakefile | 4 ++-- pom.xml | 12 ++++++++---- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 36554eac..0c54fe59 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -9,7 +9,7 @@ on: env: # Default versions for canonical release build DEFAULT_JAVA_VERSION: '8' - DEFAULT_JRUBY_VERSION: '9.4.14.0' # Should match pom.xml property (AND a version inside the test matrix) + DEFAULT_JRUBY_VERSION: '9.4.14.0' # Should match pom.xml property (AND a version inside the test matrix) DEFAULT_RACK_VERSION: '~> 2.2.0' # Should match Gemfile (AND a version inside the test matrix) jobs: @@ -42,7 +42,7 @@ jobs: cache: maven - name: Build with Maven - run: ./mvnw -B install -Djruby.version=${{ matrix.jruby_version }} + run: ./mvnw -B install -Djruby.test.version=${{ matrix.jruby_version }} env: RACK_VERSION: ${{ matrix.rack_version }} @@ -79,7 +79,6 @@ jobs: env: BUNDLE_GEMFILE: gemfiles/${{ matrix.appraisal }}.gemfile - JRUBY_VERSION: ${{ matrix.jruby_version }} steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 diff --git a/Rakefile b/Rakefile index 2522bd6f..7bf06b17 100644 --- a/Rakefile +++ b/Rakefile @@ -38,14 +38,14 @@ directory 'target/classes' desc "Compile classes" task(:compile => 'target/classes') do - sh "./mvnw compile #{ENV['JRUBY_VERSION'] ? "-Djruby.version=#{ENV['JRUBY_VERSION']}" : ""}" + sh "./mvnw compile" end directory 'target/test-classes' desc "Compile test classes" task(:test_prepare => ['target/classes', 'target/test-classes']) do - sh "./mvnw test-compile #{ENV['JRUBY_VERSION'] ? "-Djruby.version=#{ENV['JRUBY_VERSION']}" : ""}" + sh "./mvnw test-compile" end desc "Unpack the rack gem" diff --git a/pom.xml b/pom.xml index 66d97270..42c359e3 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,11 @@ UTF-8 - 9.4.14.0 + + 9.4.14.0 + + ${jruby.compat.version} + 3.0.6 ${project.build.directory}/rubygems 2.0.17 @@ -79,7 +83,7 @@ jruby-complete - ${jruby.version} + ${jruby.compat.version} provided @@ -243,7 +247,7 @@ test install - ${jruby.version} + ${jruby.test.version} false false @@ -255,7 +259,7 @@ rake-maven-plugin ${jruby.maven.plugins.version} - ${jruby.version} + ${jruby.test.version} From 1db9bb209b579fd051dee8c2850d4b9c4a541127 Mon Sep 17 00:00:00 2001 From: Chad Wilson <29788154+chadlwilson@users.noreply.github.com> Date: Fri, 17 Apr 2026 20:33:38 +0800 Subject: [PATCH 5/6] [build] display progress and mvn coloring consistently --- .github/workflows/maven.yml | 2 +- Rakefile | 11 +++++------ 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml index 0c54fe59..127716d2 100644 --- a/.github/workflows/maven.yml +++ b/.github/workflows/maven.yml @@ -42,7 +42,7 @@ jobs: cache: maven - name: Build with Maven - run: ./mvnw -B install -Djruby.test.version=${{ matrix.jruby_version }} + run: ./mvnw -ntp install -Dstyle.color=always -Djruby.test.version=${{ matrix.jruby_version }} env: RACK_VERSION: ${{ matrix.rack_version }} diff --git a/Rakefile b/Rakefile index 7bf06b17..b281c1b5 100644 --- a/Rakefile +++ b/Rakefile @@ -38,14 +38,14 @@ directory 'target/classes' desc "Compile classes" task(:compile => 'target/classes') do - sh "./mvnw compile" + sh "./mvnw -ntp -Dstyle.color=always compile" end directory 'target/test-classes' desc "Compile test classes" task(:test_prepare => ['target/classes', 'target/test-classes']) do - sh "./mvnw test-compile" + sh "./mvnw -ntp -Dstyle.color=always test-compile" end desc "Unpack the rack gem" @@ -88,7 +88,7 @@ task :test_resources => ["target/test-classes"] namespace :resources do desc "Copy (and generate) resources" task :copy => :resources do - sh './mvnw process-resources -Dmdep.skip=true' + sh './mvnw -ntp process-resources -Dstyle.color=always -Dmdep.skip=true' end desc "Generate test resources" task :test => :test_resources @@ -198,8 +198,7 @@ task :release_checks do " git push origin :#{GEM_VERSION}" if ok end - pom_version = `./mvnw help:evaluate -Dexpression=project.version`. - split("\n").reject { |line| line =~ /[INFO]/ }.first.chomp + pom_version = `./mvnw help:evaluate -q --non-recursive -DforceStdout -Dexpression=project.version` if pom_version =~ /dev|SNAPSHOT/ fail "Can't release a dev/snapshot version.\n" + "Please update pom.xml to the final release version, run `mvn install', and commit the result." @@ -219,7 +218,7 @@ task :release => [:release_checks, :clean] do args = '' args << "-Dgpg.keyname=#{ENV['GPG_KEYNAME']} " if ENV['GPG_KEYNAME'] - sh "./mvnw -Prelease #{args} -DupdateReleaseInfo=true clean deploy" + sh "./mvnw -ntp -Prelease #{args} -Dstyle.color=always -DupdateReleaseInfo=true clean deploy" sh "git tag #{GEM_VERSION}" From f5c74c298b90634c6655baa7d76f5757d23c7c0c Mon Sep 17 00:00:00 2001 From: Chad Wilson <29788154+chadlwilson@users.noreply.github.com> Date: Fri, 17 Apr 2026 20:57:13 +0800 Subject: [PATCH 6/6] [test] add test for exception capture content --- src/spec/ruby/rack/capture_spec.rb | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/spec/ruby/rack/capture_spec.rb b/src/spec/ruby/rack/capture_spec.rb index 995c1064..1d584237 100644 --- a/src/spec/ruby/rack/capture_spec.rb +++ b/src/spec/ruby/rack/capture_spec.rb @@ -13,15 +13,26 @@ before :each do JRuby::Rack.context = nil $servlet_context = @servlet_context - allow(@servlet_context).to receive(:init_parameter_names).and_return [] + allow(@servlet_context).to receive(:config).and_return Java::OrgJrubyRackEmbed::Config.new end it "captures environment information" do expect(@servlet_context).to receive(:log) - error = StandardError.new + error = StandardError.new "simulated rack start-up failed" error.capture error.store expect(error.output).to be_a StringIO + expect(error.output.string).to include "An exception happened during JRuby-Rack startup" + expect(error.output.string).to include "simulated rack start-up failed" + expect(error.output.string).to include "--- System" + expect(error.output.string).to include "jruby #{JRUBY_VERSION}" + expect(error.output.string).to include "--- Context Init Parameters:" + expect(error.output.string).to include "--- RubyGems" + expect(error.output.string).to include "Gem.path:" + expect(error.output.string).to include "--- Bundler" + expect(error.output.string).to include "Gemfile:" + expect(error.output.string).to include "--- JRuby-Rack Config" + expect(error.output.string).to include "logger_class_name" end it "captures exception backtrace" do @@ -34,4 +45,5 @@ end end + end