Use any Java JAR from JRuby (no gem required)
Use any Java JAR from JRuby (no gem required)
You don’t need a Ruby gem wrapper to use a Java library. JRuby treats .jar
files as first-class load targets — require works on them the same as on
.rb files.
Get the jar
Most Java libraries publish their releases on Maven Central. The URL pattern is
https://repo1.maven.org/maven2/{group/with/slashes}/{artifact}/{version}/{artifact}-{version}.jar
For jsoup (an HTML parser):
mkdir vendor/jsoup
curl -L -o vendor/jsoup-1.22.2.jar \
https://repo1.maven.org/maven2/org/jsoup/jsoup/1.22.2/jsoup-1.22.2.jar
Load and use it
require 'java'
require_relative 'vendor/jsoup/jsoup-1.22.2.jar'
java_import 'org.jsoup.Jsoup'
doc = Jsoup.connect("https://example.com").get
puts doc.title
puts doc.select("a").map { |a| [a.text, a.attr("href")] }
That’s the whole pattern. JRuby resolved the .jar, registered its classes
with the JVM, and java_import made org.jsoup.Jsoup available as a
top-level constant. Every public Java class in the jar is reachable
either by full name (Java::OrgJsoupNodes::Element) or by importing.
Loading a directory of jars
Some libraries ship as several jars (Lucene’s core + analysis-common +
queryparser, Jackson’s core + databind + annotations). Glob and
require all of them:
require 'java'
Dir[File.expand_path('vendor/**/*.jar', __dir__)].sort.each do |jar|
require jar
end
sort keeps the load order deterministic — useful when one jar shadows
classes from another.
Inspecting a jar with JarFile
When you want to see what’s inside before importing — for example, to
discover which packages a fat-jar bundles, or pull the version out of its
manifest — use java.util.jar.JarFile:
include "jsoup-inspect.rb"
A few good uses for this:
- Confirm a fat-jar actually bundles its dependencies (look for class
prefixes from packages you didn’t expect). - Pull
Implementation-Versionout of an unknown jar so your app can
log which build it loaded. - Double-check that a jar exports the package you’re trying to import.
Where to store jars
Pick the convention that fits the project:
vendor/checked into git. Reproducible, no network at boot,
but bloats the repo. Best for small jars and air-gapped environments.- A
Rakefiletask that curls them on first run. Repo stays light,
CI bootstraps automatically. Add the target dir to.gitignore. ~/.m2/repository/. Let Maven manage them and point JRuby at the
resolved paths. Portable across machines that havemvn, awkward for
ones that don’t.
When a gem is the right answer
If you’re shipping more than a handful of jars or want to share them
across multiple JRuby projects, package the bundle as a thin gem: a single
lib/{name}.rb whose only job is require_relative-ing the bundled jars.
Scaling up: jar-dependencies
Once a project has several Java libraries with their own transitive
dependencies, maintaining curl commands and manual jar lists becomes
fragile. The jar-dependencies gem lets you declare Java dependencies in a
gemspec and resolves the full dependency graph via an embedded Maven runtime
— no mvn in your PATH needed, and Jars.lock pins the exact versions.
See the Manage Java dependencies with jar-dependencies recipe.
Next steps
- Add a build-time step (Rake, Mage, plain shell) that fetches the jars
you need so a fresh checkout becomes runnable in one command. - For libraries that ship annotations (
@Nullable,@NotNull), grab the
annotation jar too — JRuby reflects over them at load time and will
otherwise warn at first use of an annotated class. - Browse the library’s docs on this site to find the entry-point classes
worthjava_import-ing.