jruby / jruby-rack

Rack for JRuby and Java appservers
MIT License
397 stars 137 forks source link

Is there a way to create portable "jar-bootstrap"'ed .wars? #162

Closed ngc-ptin closed 2 years ago

ngc-ptin commented 11 years ago

JRubyJars.jruby_rack_jar_path will return the exact jar path, including version numbers.

If you use this path in the MANIFEST.MF Class-Path directive, you'll create a dependency on that version of the JRubyRack gem. Unless you include all the libraries in your .war file (which, in my case, is not an option, since we manage all dependencies through RPM, including gems), this will cause portability problems if you wish to deploy your .war on a system which has a different JRubyRack version, or a different GEM_HOME, for instance.

a) anyone else had this problem? How did you solve it? b) Wouldn't it make sense, for example, to include jruby-rack as part of the jruby-complete distribution?

kares commented 11 years ago

hey @ngc-ptin, sounds pretty crazy - I'm not sure anyone ( besides you - so far :) would benefit from building a (self-sustainable) .war that depends on the environment ... esp. a changing jruby-rack versions sounds like trouble ... a) not sure what the problem actually is - but soundz like smt you would want from warbler instead, maybe ? b) certainly makes no sense ... sorry

ngc-ptin commented 11 years ago

Thanks for the answer, @kares.

Let me clarify a bit, though, since what I'm talking about isn't that crazy :) In our context, we might have N applications and their deps deployed on a given server via RPM, to avoid dependency hell and unnecessary replication of code on client machines since they'll be sharing the installed deps. It also ensures new versions of deps can be easily and cleanly swapped in in case any issues are found in the installed version. This goes for our apps, Ruby itself and gems as well. Since we repackage gems as RPMS and enforce their installation through the Yum repositories (that is, Bundler, RVM and gem install are strictly off-limits), our apps must declare their dependencies at the RPM level and not include any libs themselves.

We did try Warbler a few months ago, but we observed odd behaviors we tried to empty the bundled libs in warbler.rb. We therefore opted for a custom-made packaging solution using jar-bootstrap.rb (github.com/ptinovacao/jruby-warck). It generates minimal-sized .war files that can be run on the command line, but since MANIFEST.MF is generated using the build machine's configuration to determine a Class-Path for JRuby, rather the deployment machine's, there is the possibility that it will refer to an unavailable jarfile.

I'm guessing we'll either

but if you can think of any other approaches please do give your 2 cents :)

kares commented 11 years ago

I see - I thought you're using Warbler and than trying to avoid all the deps it packaged up fro you ... So your apps (.wars) are than started on the command line - how's that happening I mean how does it get deployed? I'm asking cause I'm also guessing there's something doing all the bootstrap to handle rpm-ized gems ... than that part could have been used (or something simple above it - shell script) to bootstrap the Class-Path for the application if you're starting the whole thing as a Java app. Also b) in this case makes sense as well (for you) ...

ngc-ptin commented 11 years ago

When you execute a .war file on the command line the bootstrap script will unzip the .war contents to a directory and simply run Puma (we use initscripts in this case). The very same .war is deployable on a servlet container.

The RPMized gems just get installed in the typical /usr/share/gems (by default), no special handling needs to be done in the general case. Are you suggesting defining the MANIFEST.MF on install time depending on the target system? Not sure I understood your idea

kares commented 11 years ago

OK, so puma does not need jruby-rack so it's only relevant to know the servet container deployment details. I assume it's not hacked in any way - the war needs jruby-rack packed that's for sure for it's Java servlet part, now unless it's Trinidad or a "similar" server (scripted in JRuby) you can't get around it at least not for the Java part. That's going to be baked in WEB-INF/lib folder or how else assuming you are packaging that up ... Otherwise you should be able to get around things by using the "latest" gem (without Bundler) (e.g. in Trinidad). The other solution would be to pack it with the servlet container - assuming you use one and exclude it from .war

I might to smt about https://github.com/jruby/jruby-rack/blob/master/Rakefile#L146 - so that one can specify his "own" jar-path before using the default - but that still won't help you really, as fas as I understand.