Say you wanted to store some information across different calls to your JRuby/Rails application on the server side. You could use a database, or memcached. However, what if you just want to do something very simple like a basic cache, and you don’t have a database for your application? Memcached seems like overkill, and would complicate your deployment considerably. So, what about just using statics?
Well, you can’t do it in Ruby, as the Rails integration servlet spawns multiple instances of the JRuby interpreter.
Ruby code in a page view:
<h1>Ruby global number</h1> <% $i ||= 0 %> <% $i += 1 %> <%= $i %> <h1>Ruby obj id</h1> <% $o ||= Object.new %> <%= $o.object_id %>
Results between multiple refreshes of the page:
Ruby global number 1 Ruby obj id 244 Ruby global number 1 Ruby obj id 256 Ruby global number 2 Ruby obj id 244 Ruby global number 2 Ruby obj id 256
Our requests seem to be switching between two instances of the Ruby interpreter.
However, we *can* do it in Java. My clever, Java-literate colleagues explained that Java application servers and servlet containers use a single instance of the JVM, but have a class loader for each application. The class loader stores class information and static values. This means that within one application, the static values will be maintained between requests, but a different application on the same server will have its own set of unrelated static values (similar to AppDomains in .NET).
If we add a call to a static method in Java that increments an integer and returns it, our view looks like this:
<h1>Ruby global number</h1> <% $i ||= 0 %> <% $i += 1 %> <%= $i %> <h1>Ruby obj id</h1> <% $o ||= Object.new %> <%= $o.object_id %> <h1>Java incrementing static integer</h1> <%= TestClass.incrementAndReturnNumber() %>
Our results now look a lot more useful. The Java static integer is getting incremented each call to the view:
Ruby global number 1 Ruby obj id 244 Java number 1 Ruby global number 1 Ruby obj id 256 Java number 2 Ruby global number 2 Ruby obj id 244 Java number 3 Ruby global number 2 Ruby obj id 256 Java number 4
From this little experiment, Java statics seem like a possible way to go for storing temporary data on the server side (eg, a cache implemented as a singleton) for JRuby / Rails. Another option may be to use the ServletContext from the JRuby Rails integration servlet – probably an area worth investigating.
How about using a file to store your static data? In Ruby every time you change that static number or data just update that file. I had done that for a php app once for implementing page hit counters.
I’m pretty sure one of the built-in caching mechanisms in Rails is to write out static html pages which then get served up by the web server directly. Though, if you want to cache certain values only, your approach seems useful.
Thanks for your comment. You could indeed store data in a file and it sounds great for a counter. I’m thinking it would be less fun for a cache though, as the cache could easily be multi-megabytes in size – ie, in need of indexing similar. It would also have more speed overhead than in memory with the disk reads, especially if the file was stored on a network drive rather than local (as in some production deployment environments).