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?
on 2012-06-24 17:21
on 2012-06-24 17:36
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": http://pragprog.com/book/jkdepj/deploying-with-jruby I also discuss TorqueBox Knob files, which provide many of the same advantages as WAR files. -Joe
on 2012-06-24 17:39
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.
on 2012-06-25 11:38
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.
on 2012-06-25 17:19
On Sun, Jun 24, 2012 at 10:36:16AM -0500, Joe Kutner wrote: > 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. > > 4) 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
on 2012-06-25 17:47
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 :) I should probably take two apps that are identical and run on JRuby and MRI and benchmark their respective deployments. Would be interesting.
on 2012-06-26 17:39
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.