Skip to content

declare jars inside gemspec

Christian Meier edited this page Aug 18, 2014 · 3 revisions

the notation of the jar or pom dependencies inside a gemspec file is the same as with JBundler's Jarfile

this declaration goes into the requirements part of the Gem::Specification

Gem::Specification.new do |s|
  s.requirements << "jar org.bouncycastle:bcpkix-jdk15on, 1.50"
  s.requirements << "jar 'org.bouncycastle:bcprov-jdk15on', '1.50'"
end

note: the parentheses are optional and the declaration is NOT ruby code - you just can declare jars and poms here.

it is also possible to add a maven scope to it

Gem::Specification.new do |s|
  s.requirements << "jar org.bouncycastle:bcpkix-jdk15on, 1.50, :scope => :provided"
  s.requirements << "jar 'org.bouncycastle:bcprov-jdk15on', '1.50', :scope => :test"
end

embed the jars without jar-dependencies gem as runtime dependency

in case you do not want a jar-dependencies gem as runtime dependency you still can use the jar declaration inside the gemspec file and use the jar-dependencies feature of "tracking" the versions of the required jars.

excerpt from https://github.com/jruby/jruby-openssl/blob/master/jruby-openssl.gemspec

Gem::Specification.new do |s|
  s.requirements << "jar org.bouncycastle:bcpkix-jdk15on, #{Jopenssl::Version::BOUNCY_CASTLE_VERSION}"
  s.requirements << "jar org.bouncycastle:bcprov-jdk15on, #{Jopenssl::Version::BOUNCY_CASTLE_VERSION}"

  s.add_development_dependency 'jar-dependencies', '0.0.4'
end

and the part which loads the jars looks like this (https://github.com/jruby/jruby-openssl/blob/master/lib/jopenssl/load.rb#L6

begin
  # if we have jar-dependencies we let it track the jars
  require 'jar-dependencies'
  require_jar( 'org.bouncycastle', 'bcpkix-jdk15on', Jopenssl::Version::BOUNCY_CASTLE_VERSION )
  require_jar( 'org.bouncycastle', 'bcprov-jdk15on', Jopenssl::Version::BOUNCY_CASTLE_VERSION )
rescue LoadError
  require "org/bouncycastle/bcpkix-jdk15on/#{Jopenssl::Version::BOUNCY_CASTLE_VERSION}/bcpkix-jdk15on-#{Jopenssl::Version::BOUNCY_CASTLE_VERSION}.jar"
  require "org/bouncycastle/bcprov-jdk15on/#{Jopenssl::Version::BOUNCY_CASTLE_VERSION}/bcprov-jdk15on-#{Jopenssl::Version::BOUNCY_CASTLE_VERSION}.jar"
end

embed the jars with jar-dependencies gem as runtime dependency

there is no real need to leave out the jar-dependencies gem, then the above examples will look like this:

Gem::Specification.new do |s|
  s.requirements << "jar org.bouncycastle:bcpkix-jdk15on, 1.50"
  s.requirements << "jar org.bouncycastle:bcprov-jdk15on, 1.50"
  s.add_runtime_dependency 'jar-dependencies', '~> 0.0.8'
end

and the loading code

require 'jar-dependencies'
require_jar( 'org.bouncycastle', 'bcpkix-jdk15on', '1.50' )
require_jar( 'org.bouncycastle', 'bcprov-jdk15on', '1.50' )

drawback: installing the gem the jar installer will generate a file _jars.rb. see also next example on how to use it and you duplicate the "declaration" between the gemspec and the loading code.

embed the jars with complex dependency tree

the above example is simple since there are no transitive dependencies of those embedded jars. here is an more complex jar dependency

Gem::Specification.new do |s|
  s.requirements << 'jar org.apache.solr:solr-solrj:4.9.0'
  s.add_runtime_dependency 'jar-dependencies', '~> 0.0.8'
end

in such a case it is not feasible to write up the require_jar statements for all those transitive jar dependencies.

a rake task can help:

require 'jar_installer'

desc 'setup jar dependencies and generates <gemname>_jars.rb'
task :setup do
  Jars::JarInstaller.install_jars
end

this rake task reduces the loading code to require '<gemname>_jars.rb'

when you install such a gem the _jars.rb will be generated again which is important in the case the jar dependencies uses version ranges instead of 'maven fixed version hints'. in case of the fixed version hints the generated file will be the same for both - the development case and during installation. so best use maven fixed version for your jar dependencies.