Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions .github/workflows/maven.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ on:

env:
# Default versions for canonical release build
DEFAULT_JAVA_VERSION: '8'
DEFAULT_JRUBY_VERSION: '10.0.6.0' # Should match pom.xml <jruby.compat.version> property (AND a version inside the test matrix)
DEFAULT_JAVA_VERSION: '21'
DEFAULT_JRUBY_VERSION: '9.4.15.0' # Should match pom.xml <jruby.compat.version> 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:
Expand All @@ -19,7 +19,7 @@ jobs:

strategy:
matrix:
jruby_version: [ '10.0.6.0', '10.1.1.0' ]
jruby_version: [ '9.4.15.0', '10.0.6.0', '10.1.1.0' ]
java_version: [ '21', '25' ]
rack_version: [ '~> 2.2.0' ]
fail-fast: false
Expand Down Expand Up @@ -55,8 +55,11 @@ jobs:
'rails72_rack22',
'rails80_rack22',
]
jruby_version: [ '10.0.6.0', '10.1.1.0' ]
jruby_version: [ '9.4.15.0', '10.0.6.0', '10.1.1.0' ]
java_version: [ '21', '25' ]
exclude:
- appraisal: 'rails80_rack22'
jruby_version: '9.4.15.0' # Rails 8 requires Ruby 3.4 compatibility, which JRuby 9.4 does not support
fail-fast: false

env:
Expand Down
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
- Officially support Javax Servlet API 4.0 (JEE 8)

Breaking compatibility changes
- Drop support for JRuby 9.x
- Drop support for Java < 21
- Drop support for JRuby < 9.4
- Drop support for Rails < 7.2

Breaking behavioral changes
Expand Down
82 changes: 59 additions & 23 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@ For more information on Rack, visit http://rack.github.io/.

## Compatibility

| JRuby-Rack Series | Status | Rack | JRuby | Java | Rails | Target Servlet API | Notes |
|----------------------------------------------------------------|---------------|-----------|-------------|------|-----------|---------------------|----------------------------------------------------------------|
| **2.0 (_planned_, _unreleased_)** | Dev | 2.2 | 10.0 → 10.1 | 21+ | 7.2 → 8.0 | 5.0+ (Jakarta EE 9) | ❌ Servlet < 5.0 containers will not work |
| **1.3 (master, _unreleased_)** | Dev | 2.2 | 10.0 → 10.1 | 21+ | 7.2 → 8.0 | 4.0 (Java EE 8) | ✅ _Unofficial_: Servlet 2.5 → 3.1 & Rails 6.1 → 7.1 also likely OK. |
| [**1.2**](https://github.com/jruby/jruby-rack/tree/1.2-stable) | Maintained | 2.2 | 9.3 → 10.1 | 8+ | 5.0 → 8.0 | 3.0 (Java EE 6) | ✅ _Unofficial_: Servlet 3.1 → 4.0 also OK with most containers |
| [**1.1**](https://github.com/jruby/jruby-rack/tree/1.1-stable) | EOL @ 2024-05 | 1.x → 2.2 | 1.6 → 9.4 | 6+ | 2.1 → 5.2 | 2.5 (Java EE 5) | ✅ _Unofficial_: Servlet 3.0 → 4.0 also OK with most containers |
| [**1.0**](https://github.com/jruby/jruby-rack/tree/1.0.10) | EOL @ 2011-11 | 0.9 → 1.x | 1.1 → 1.9 | 5+ | 2.1 → 3.x | 2.5 (Java EE 5) | |
| JRuby-Rack Series | Status | Rack | JRuby | Java | Rails | Target Servlet API | Notes |
|----------------------------------------------------------------|---------------|-----------|------------|------|-----------|---------------------|---------------------------------------------------------------------|
| **2.0 (_planned_, _unreleased_)** | Dev | 2.2 | 9.4 → 10.1 | 21+ | 7.2 → 8.0 | 5.0+ (Jakarta EE 9) | ❌ Servlet < 5.0 containers will not work |
| **1.3 (master, _unreleased_)** | Dev | 2.2 | 9.4 → 10.1 | 21+ | 7.2 → 8.0 | 4.0 (Java EE 8) | ✅ _Unofficial_: Servlet 2.5 → 3.1 & Rails 6.1 → 7.1 also likely OK |
| [**1.2**](https://github.com/jruby/jruby-rack/tree/1.2-stable) | Maintained | 2.2 | 9.3 → 10.1 | 8+ | 5.0 → 8.0 | 3.0 (Java EE 6) | ✅ _Unofficial_: Servlet 3.1 → 4.0 also OK with most containers |
| [**1.1**](https://github.com/jruby/jruby-rack/tree/1.1-stable) | EOL @ 2024-05 | 1.x → 2.2 | 1.6 → 9.4 | 6+ | 2.1 → 5.2 | 2.5 (Java EE 5) | ✅ _Unofficial_: Servlet 3.0 → 4.0 also OK with most containers |
| [**1.0**](https://github.com/jruby/jruby-rack/tree/1.0.10) | EOL @ 2011-11 | 0.9 → 1.x | 1.1 → 1.9 | 5+ | 2.1 → 3.x | 2.5 (Java EE 5) | |

## Getting Started

Expand Down Expand Up @@ -332,46 +332,82 @@ the generated jar should be located at `target/jruby-rack-*.jar`
Alternatively use Rake, e.g. to build the gem (skipping specs) :

```shell
jruby -S rake clean gem SKIP_SPECS=true
rake clean gem SKIP_SPECS=true
```

You can **not** use JRuby-Rack with Bundler directly from the git (or http) URL
(`gem 'jruby-rack', :github => 'jruby/jruby-rack'`) since the included .jar file
is compiled and generated on-demand during the build (it would require us to
package and push the .jar every time a commit changes a source file).

## Releasing
## Testing

Releasing must be done by users authorized to push to the `org.jruby` group ID on https://central.sonatype.org and to push the `jruby-rack` gem to https://rubygems.org.
JRuby-Rack is always compiled against the version defined by `jruby.compat.version` in `pom.xml`. By default, tests
will be run with this default version.

* Make sure auth is configured for "central" repository ID in your `.m2/settings.xml`
* Update the versions in `pom.xml` and `src/main/ruby/jruby/rack/version.rb` to the release version
* Commit the version update locally
* Run `./mvnw deploy -Prelease` to build, sign, and push all artifacts to Maven Central staging
* Confirm the release completes publishing at `https://central.sonatype.org`
* `rake clean gem SKIP_SPECS=true` and push the gem
* Tag the release version in git
* Update the versions again to the next dev version (`-SNAPSHOT` for the Maven artifact in `pom.xml` and `.SNAPSHOT` for the gem in `version.rb`)
* Push all commits and tags to GitHub
Run tests against a specific JRuby version:

```shell
./mvnw test -Djruby.test.version=10.1.1.0
```

Or via JRuby/Rake with the local JRuby version implied by your path:
```shell
bundle install
rake spec
```

Filter for specific specs:

```shell
SPEC=src/spec/ruby/rack/application_spec.rb ./mvnw test
# or
SPEC=src/spec/ruby/rack/application_spec.rb rake spec
```

### Run appraisals alongside different real Rails/Rack versions

JRuby-Rack defaults to run specs with a Rails stub. You can run the specs against a real Rails version using the Gemfiles
managed by the `Appraisals` gem.

```shell
export BUNDLE_GEMFILE=gemfiles/rails72_rack22.gemfile
bundle install
bundle exec rake spec
```

## Adding testing for new Rails versions
### Adding testing for new Rails versions

* Add the new version to `.github/workflows/maven.yml` under the `matrix` section
* Add a new configuration to the `Appraisals` file, then
```bundle exec appraisal generate```
```bundle exec appraisal generate```
* Generate a new stub Rails application for the new version
```shell
VERSION=rails72
cd src/spec/stub
rm -rf $VERSION && BUNDLE_GEMFILE=~/Projects/community/jruby-rack/gemfiles/${VERSION}_rack22.gemfile bundle exec rails new $VERSION --minimal --skip-git --skip-docker --skip-active-model --skip-active-record --skip-test --skip-system-test --skip-dev-gems --skip-bundle --skip-keeps --skip-asset-pipeline --skip-ci --skip-brakeman --skip-rubocop
```
* Manual changes to make to support testing
* In `config/production.rb` comment out the default `config.logger` value so jruby-rack applies its own `RailsLogger`.
* In `config/production.rb` comment out the default `config.logger` value so jruby-rack applies its own `RailsLogger`.

## Releasing

Releasing must be done by users authorized to push to the `org.jruby` group ID on https://central.sonatype.org and to push the `jruby-rack` gem to https://rubygems.org.

* Make sure auth is configured for "central" repository ID in your `.m2/settings.xml`
* Update the versions in `pom.xml` and `src/main/ruby/jruby/rack/version.rb` to the release version
* Commit the version update locally
* Run `./mvnw deploy -Prelease` to build, sign, and push all artifacts to Maven Central staging
* Confirm the release completes publishing at `https://central.sonatype.org`
* `rake clean gem SKIP_SPECS=true` and push the gem
* Tag the release version in git
* Update the versions again to the next dev version (`-SNAPSHOT` for the Maven artifact in `pom.xml` and `.SNAPSHOT` for the gem in `version.rb`)
* Push all commits and tags to GitHub

## Support

Please use [github][3] to file bugs, patches and/or pull requests.
More information at the [wiki][4] or ask us at **#jruby**'s IRC channel.
More information at the [wiki][4] or ask us on our Matrix room at **#jruby:matrix.org**.

[1]: https://github.com/jruby/warbler
[2]: https://central.sonatype.com/artifact/org.jruby.rack/jruby-rack
Expand Down
2 changes: 1 addition & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ task :gem => [target_jar, target_jruby_rack, target_jruby_rack_version] do
gem.email = ['nick@nicksieger.com']
gem.files = FileList["./**/*"].exclude("*.gem").map{ |f| f.sub(/^\.\//, '') }
gem.homepage = %q{http://jruby.org}
gem.required_ruby_version = '>= 3.4.0' # JRuby >= 10.0
gem.required_ruby_version = '>= 3.1.0' # JRuby >= 9.4
end

require 'rubygems/package'
Expand Down
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ This directory includes samples using JRuby-Rack to build Rack web applications
into Java app servers.

- All use [Warbler](https://github.com/jruby/warbler) to do so for easy of packaging.
- Require JRuby `10.0` and a compatible JVM (Java `21` -> `25`).
- Require JRuby `9.4` and a compatible JVM (Java `21` -> `25`).

### Building/running

Expand Down
4 changes: 3 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -243,13 +243,15 @@
<groupId>org.jruby.maven</groupId>
<artifactId>bundler-maven-plugin</artifactId>
<version>${jruby.maven.plugins.version}</version>
<configuration>
<jrubyVersion>${jruby.test.version}</jrubyVersion>
</configuration>
<executions>
<execution>
<id>bundle-install</id>
<phase>test</phase>
<goals><goal>install</goal></goals>
<configuration>
<jrubyVersion>${jruby.test.version}</jrubyVersion>
<local>false</local>
<quiet>false</quiet>
</configuration>
Expand Down
7 changes: 4 additions & 3 deletions src/main/java/org/jruby/rack/embed/Dispatcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
import java.io.IOException;

import org.jruby.Ruby;
import org.jruby.api.Access;
import org.jruby.javasupport.JavaUtil;
import org.jruby.rack.AbstractRackDispatcher;
import org.jruby.rack.DefaultRackApplication;
Expand All @@ -19,6 +18,7 @@
import org.jruby.rack.RackEnvironment;
import org.jruby.rack.RackInitializationException;
import org.jruby.rack.RackResponseEnvironment;
import org.jruby.rack.util.JRubyCompat;
import org.jruby.runtime.ThreadContext;
import org.jruby.runtime.builtin.IRubyObject;

Expand All @@ -44,8 +44,9 @@ private void initialize() {
}
ThreadContext currentContext = runtime.getCurrentContext();
// `JRuby::Rack.context = context`
Access.getModule(currentContext, "JRuby")
.getConstantAt(currentContext, "Rack")
//noinspection deprecation getConstant without context is deprecated in 9.4 but not removed in 10.0 or 10.1
JRubyCompat.getModule(currentContext, "JRuby")
.getConstant("Rack")
.callMethod(currentContext, "context=", JavaUtil.convertJavaToRuby(runtime, context));
}

Expand Down
21 changes: 10 additions & 11 deletions src/main/java/org/jruby/rack/ext/Input.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
import org.jruby.RubyObject;
import org.jruby.RubyString;
import org.jruby.anno.JRubyMethod;
import org.jruby.api.Access;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.rack.RackEnvironment;
import org.jruby.rack.servlet.RewindableInputStream;
import org.jruby.rack.util.ExceptionUtils;
import org.jruby.rack.util.JRubyCompat;
import org.jruby.runtime.Block;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
Expand All @@ -40,30 +40,29 @@ public class Input extends RubyObject {

static final ObjectAllocator ALLOCATOR = Input::new;

static RubyClass getClass(final Ruby runtime) {
return Access.getClass(runtime.getCurrentContext(), "JRuby", "Rack", "Input");
}

private boolean rewindable;
private InputStream input;
private int length = 0;

private Input(Ruby runtime) {
this(runtime, JRubyCompat.getClass(runtime.getCurrentContext(), "JRuby", "Rack", "Input"));
}

protected Input(Ruby runtime, RubyClass klass) {
super(runtime, klass);
}

public Input(Ruby runtime, final RackEnvironment env) {
super(runtime, getClass(runtime));
this(runtime);
initialize(env);
}

public Input(Ruby runtime, final InputStream input, final int length) {
this(runtime, input, false, length);
}

public Input(Ruby runtime, final InputStream input, final boolean rewindable,
final int length) {
super(runtime, getClass(runtime));
public Input(Ruby runtime, final InputStream input, final boolean rewindable, final int length) {
this(runtime);
this.rewindable = rewindable;
this.setInput( input );
this.length = length;
Expand Down Expand Up @@ -132,15 +131,15 @@ public IRubyObject gets(final ThreadContext context) {
public IRubyObject read(final ThreadContext context, final IRubyObject[] args) {
int readLen = 0;
if ( args.length > 0 ) {
long len = args[0].convertToInteger("to_i").asLong(context);
long len = JRubyCompat.toLong(context, args[0]);
readLen = (int) Math.min(len, Integer.MAX_VALUE);
}
final RubyString buffer = args.length > 1 ? args[1].asString() : null;
try {
final byte[] bytes = readUntil(MATCH_NONE, readLen);
if ( bytes != null ) {
if ( buffer != null ) {
buffer.clear(context);
JRubyCompat.clearString(context, buffer);
buffer.catWithCodeRange(new ByteList(bytes, false), StringSupport.CR_UNKNOWN);
return buffer;
}
Expand Down
17 changes: 7 additions & 10 deletions src/main/java/org/jruby/rack/ext/Logger.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@
import org.jruby.RubyTime;
import org.jruby.anno.JRubyClass;
import org.jruby.anno.JRubyMethod;
import org.jruby.api.Access;
import org.jruby.exceptions.RaiseException;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.rack.RackContext;
import org.jruby.rack.RackLogger;
import org.jruby.rack.logging.ServletContextLogger;
import org.jruby.rack.util.JRubyCompat;
import org.jruby.runtime.Block;
import org.jruby.runtime.ObjectAllocator;
import org.jruby.runtime.ThreadContext;
Expand Down Expand Up @@ -87,7 +87,8 @@ protected Logger(Ruby runtime, RubyClass metaClass) {
@Override
@JRubyMethod(required = 0)
public IRubyObject initialize(final ThreadContext context) {
initialize(Access.getModule(context, "JRuby").getConstant(context, "Rack").callMethod(context, "context") ); // JRuby::Rack.context
//noinspection deprecation getConstant without context is deprecated in 9.4 but not removed in 10.0 or 10.1
initialize(JRubyCompat.getModule(context, "JRuby").getConstant("Rack").callMethod(context, "context") ); // JRuby::Rack.context
return this;
}

Expand Down Expand Up @@ -144,7 +145,7 @@ public IRubyObject set_level(final ThreadContext context, final IRubyObject leve
this.level = LEVEL_NOT_SET;
return level;
}
this.level = toInt(level);
this.level = JRubyCompat.toInt(context, level);
return get_level(context);
}

Expand Down Expand Up @@ -346,7 +347,7 @@ public IRubyObject unknown(final ThreadContext context, final Block block) {
public IRubyObject add(final ThreadContext context, final IRubyObject[] args, final Block block) {
int severity = UNKNOWN;
final IRubyObject sev = args[0];
if ( !sev.isNil() ) severity = toInt(sev);
if ( !sev.isNil() ) severity = JRubyCompat.toInt(context, sev);
IRubyObject msg;
if ( args.length > 1 ) {
msg = args[1];
Expand Down Expand Up @@ -426,7 +427,7 @@ private IRubyObject format_message(final ThreadContext context,

@JRubyMethod(visibility = Visibility.PRIVATE)
public IRubyObject format_severity(final ThreadContext context, final IRubyObject sev) {
return RubyString.newStringShared(context.runtime, formatSeverity(toInt(sev)));
return RubyString.newStringShared(context.runtime, formatSeverity(JRubyCompat.toInt(context, sev)));
}

private static final ByteList FORMATTED_DEBUG =
Expand All @@ -453,10 +454,6 @@ private static ByteList formatSeverity(final int severity) {
};
}

private static int toInt(final IRubyObject level) {
return level.convertToInteger("to_i").asInt(level.getRuntime().getCurrentContext());
}

@SuppressWarnings("unchecked")
@Override
public <T> T toJava(Class<T> target) {
Expand Down Expand Up @@ -495,7 +492,7 @@ public IRubyObject initialize(final ThreadContext context, final IRubyObject[] a
final IRubyObject rackContext;
if ( args != null && args.length > 0 ) rackContext = args[0];
else {
IRubyObject jrubyRack = Access.getModule(context, "JRuby").getConstant("Rack");
IRubyObject jrubyRack = JRubyCompat.getModule(context, "JRuby").getConstant("Rack");
rackContext = jrubyRack.callMethod(context, "context"); // JRuby::Rack.context
}
if ( rackContext.isNil() ) {
Expand Down
Loading
Loading