views:

257

answers:

4

I have a an object that I'd like to grab the contents of in java. The only problem is that is is currently in ruby.

irb(main):050:0> blah
=> "BAh7ByIeYXV0aGVudGljYXRpb25fc3RyYXRlZ2llczAiCXVzZXJpBg%253D%253D-\
-0cdecf4edfaa5cbe4693c9fb83b204c1256a54a6"

irb(main):049:0> Marshal.load(Base64.decode64(blah))
=> {"authentication_strategies"=>nil, "user"=>1}

I got the base64 portion allright -- so now everything is in bytes. How would i access that 2nd string? I presume something can be done with jruby but I've never used it before and would have no clue where to start.

let me elaborate on my problem here.

1) these are cookies that I'm trying to share between a servlet on tomcat and a merb app on apache

2) I am not going to be storing them in the database. I have thought about using them in memcached but for other reasons I'd like to store them as cookies (yes I'm well aware of the security implications involved)

I am currently looking at jruby's Red Bridge/jruby-embed, however since this is only like 70 bytes I need to look at I think it's ridiculous to call up all that overhead for something so simple.

rather than start up a new question.... code I have right now looks like so:

        // using commons
        Base64 b64 = new Base64();
        byte[] decoded = b64.decode(cookie.getValue().getBytes());

        ScriptingContainer container = new ScriptingContainer();
        container.runScriptlet("la = Marshal.load(\"" + decoded + "\"); puts la.to_s;");

obviously this isn't going to work cause marshal is going to check the first 2 bytes of decoded and freak out since it doesn't match jruby's major/minor version....hrmss..

+3  A: 

For a solution not involving JRuby, Why don't you serialize the fields you are interested in yourself? For example, saving them as raw strings into a file or to a relational database?

I realize that this may not exactly answer the question but it may be a possibility that you hadn't previously thought of!

EDIT - feydr has made it clear that he was not talking about serializing object data to a file. I presume therefore that the serialization is for inter-process communication, in which case a binary protocol (or any protocol really) delivered via sockets isa good solution and easy to implement. You could do worse than to have a look at Google protocol buffers (it can even do code generation on the Java side).

oxbow_lakes
file io is expensive for storing session information and is definitely out...our main web app is ruby and there is no way I'm looking in a file every time a page is hitI don't have benchmarks to prove it but using a database for a session sounds pretty hard on the database -- care to provide any case examples on this?really memcache is what I'm thinking right now if there is no answer to this problem
feydr
Apologies - I thought that, given you were talking about serialization/marshalling, that file IO was *exactly* what you were doing! You could always try using a binary protocol over sockets
oxbow_lakes
A: 

how about using json for serialization?

tosh
A: 

You may also consider using Google protocol buffers which are available for Ruby and Java (as well as C++ and Python).

Dmitry
+1  A: 

Ok! This is what I did. Let me re-iterate my whole purpose here was to get a cookie session from merb to a servlet running under tomcat.

import java.io.*;
import java.util.*;
import org.jruby.embed.ScriptingContainer;
import org.apache.commons.codec.binary.Base64;
import javax.servlet.*;
import javax.servlet.http.*;

public class process extends HttpServlet {

  public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
   HttpSession session = request.getSession(true);

    PrintWriter out = response.getWriter();
    Cookie[] cookies = request.getCookies();

    for(int i=0; i<cookies.length; i++) {
      Cookie cookie = cookies[i];

      // base64 decode, then un-marshall ruby style...
      // finally figure out what to do with our session secret key
      if(cookie.getName().equals("_session_id")) {
        ScriptingContainer container = new ScriptingContainer();
        container.setWriter(out);
        container.runScriptlet("require 'base64'; puts \"" + cookie.getValue() + "\"; " +
                              "puts Marshal.load(Base64.decode64(\"" + cookie.getValue() + "\")).to_s; ");
      }                       

    } 

}     
}

Obviously this code can be cleaned up quite a lot -- eg: moving the base64 decoding back to java -- but this will get a cookie from merb. Now I just need to throw the validator in there to make sure this isn't forged.

Thanks for your suggestions everyone!

feydr