Why .war files?

I’m new to JRuby and maybe I’m missing something that’s blindingly
obvious to everyone else.

I can understand that there are corporate situations where a JRuby/Rails
developer has no option but to package their product into a .war file
and hand it over to the people that administer the webservers.

But someone developing their own product isn’t obliged to comply with
any corporate edict about how a webserver is run and I can’t see why you
would bother with packaging things into a .war file. It seems it would
be much easier to include, say, Trinidad or Mizuno in your application
and just copy the entire application onto the server - assuming the
server is running the JVM.

Is there some advantage to .war files that I don’t understand and which
justifies the extra complexity?

There are a few advantages to using a WAR file instead of a directory of
loose files:

  1. Security - a WAR can be signed to ensure that it has not been
    tampered with or corrupted along the way. If it has, the server won’t
    deploy it.
  2. Consistency - you can package all of your apps dependencies into to a
    WAR. This eliminates the need to run bundle install at deployment
    time, which is slow and sometimes unreliable.
  3. Portability - deploying a WAR file is pretty much the same on
    Windows, Linux, etc. (more so than a capistrano deployment).
  4. Speed - WAR file deployments are typically faster than capistrano for
    a number of reasons (including #2 above).
  5. Privacy - you can compile your ruby code into byte code inside of a
    WAR file to obfuscate it (useful if you are deploying to untrusted
    environments).

But there are disadvantages too:

  1. Making your development environment match your production environment
    is difficult (because you don’t want to regenerate a WAR file after
    every code change).
  2. Warbler doesn’t provide any extensions like Trinidad does for
    scheduled jobs, resque, etc. It really just handles the web part.

I go into more detail about this in my book, “Deploying with JRuby”:

I also discuss TorqueBox Knob files, which provide many of the same
advantages as WAR files.

-Joe

Aside from the fact that they’re self-contained (a single file to copy,
rather than a whole directory tree), not really. If you don’t have an
entrenched Java app server, and are comfortable with Ruby-style
deployment,
Torquebox or Trinidad are likely preferable to using something like
warbler.

All the deps. are bundled in, it’s just a cleaner way of keeping things
together in my experience. Bundle in a Jetty or something (pretty sure
Warbler supports that now) and you don’t need anything else.

Yea, if the code changes are small and there are no dependency changes,
I suppose Capistrano is the winner. I’ve typically used a CI server to
generate the WAR file continuously, so I wasn’t including the cost of
building the artifact and putting the deps in it. My WARs are ready to
go when I “push the button”.

So let me clarify my claim of speed:

  • transfer of app code and dependencies (the whole app) to the
    production can be faster.
  • hot deployment of a WAR file can be faster than restarting a bunch of
    processes with Unicorn or passenger - assuming you have more than one :slight_smile:

I should probably take two apps that are identical and run on JRuby and
MRI and benchmark their respective deployments. Would be interesting.

Thanks for all the helpful information. I guess it has largely confirmed
what I suspected.

I have been experimenting with including a copy of JRuby (not just the
.war) in my app which means that all of the gems for that app are
automatically included and can’t be confused with the gems for any other
app. Then if I put the entire app (including JRuby) in a .zip or .tar.gz
it can be easily copied anywhere with no external dependencies and when
extracted it behaves just like on the development PC. If I include a
short
shell script or batch file it can be started with a double-click. If
it’s a Rails app and I include Mizuno then it will run anywhere the JVM
exists.

The .zip or .tar.gz is no bigger than the .war version of JRuby and
there are no complications about including gems - which is more
difficult with the jruby.war.

And when I do it this way there seems to be no advantage to using RVM
(which
is great for MRI Ruby) or Bundler which does things that I don’t
expect and has very inadequate documentation.

On Sun, Jun 24, 2012 at 10:36:16AM -0500, Joe K. wrote:

  1. Consistency - you can package all of your apps dependencies into to a WAR.
    This eliminates the need to run bundle install at deployment time, which is
    slow and sometimes unreliable.

  2. Speed - WAR file deployments are typically faster than capistrano for a
    number of reasons (including #2 above).

Hm, this is the opposite of my experience. I wonder if I am doing
something
wrong?

With Capistrano, I can do an incremental source-code update, then
hot-restart
Unicorn (or whatever). On my ci server, the common case is that no
dependencies
have changed, so bundle install is minimal.

With Warbler/Glassfish, building the 100MB WAR file (Rails app with fair
number
of deps) takes a good minute or so, and deploying takes even longer.

I have yet to dig into what parts take how long; there are actions that
Glassfish takes before invoking any of my code, and actions
JRuby-Rack+my-code
take to initialize.

What sort of WAR file size are you typically dealing with? Was there
anything
specific you did to get things to go fast? One thought I had is that
Warbler
does not set ‘<webapp metadata-complete=“true” …>’ in web.xml, but I
would
only expect a minor speed up after that.

Thanks,
Patrick