Announcement Announcement Module
Collapse
No announcement yet.
StoredProcedure with jruby Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • StoredProcedure with jruby

    Thank you for this great project!

    I'm now translating example from chapter 11 'Data access using JDBC' to ruby. I was at the storedProcedure point 11.4.4 (invoking oracle sysdate procedure call).

    My code is:
    Code:
    require 'java'
    
    include_class 'org.test.Messenger'
    
    java_import "org.springframework.jdbc.core.SqlOutParameter"
    java_import "org.springframework.jdbc.object.StoredProcedure"
    java_import "org.springframework.jdbc.core.RowMapper"
    
    java_import "java.sql.Types"
    
    java_import "java.util.HashMap"
    
    class RubyMessenger 
      include Messenger
    
     def setMessage(message)
      @@message = message
     end
    
     def setDataSource(data_source)
      @@data_source = data_source
     end
    
     def getMessage
       puts "called getMessage"
       "<#{@@message}> at #{get_time}"
     end
     
     private 
     def get_time
       time_result = TimeStoredProcedure.new(@@data_source)
       puts "#{time_result} of class #{time_result.class}"
       time_result.execute.entrySet.iterator.each do |t|
         puts "#{t.inspect} of class #{t.class}"
       end
     end
    
     class TimeStoredProcedure < StoredProcedure 
       def initialize(ds)      
         sql = "sysdate"
         super(ds, sql)
         setDataSource(ds)
         setFunction(true)
         setSql(sql)
         declareParameter(SqlOutParameter.new('date', java.sql.Types::DATE))
         compile
       end
    
       def execute
         puts "executing ..."
    #the 'sysdate' sproc has no input parameters, so an empty Map is supplied...
         empty = HashMap.new
         res = super.execute(empty)
         puts "done #{res}, #{res.class}"
         res
       end
    
     end
    
    end
    
    RubyMessenger.new
    The storedProcedure is called from getMessage procedure, which is called in the main class.

    The error is:

    [INFO] ------------------------------------------------------------------------
    [ERROR] BUILD ERROR
    [INFO] ------------------------------------------------------------------------
    [INFO] An exception occured while executing the Java class. null

    0
    where the '0' is a

    Caused by: java.lang.ArrayIndexOutOfBoundsException: 0
    at org.jruby.java.dispatch.CallableSelector.exactMatc h(CallableSelector.java:244)
    at org.jruby.java.dispatch.CallableSelector.access$00 0(CallableSelector.java:26)
    at org.jruby.java.dispatch.CallableSelector$1.accept( CallableSelector.java:215)
    at org.jruby.java.dispatch.CallableSelector.findCalla ble(CallableSelector.java:143)
    at org.jruby.java.dispatch.CallableSelector.findMatch ingCallableForArgs(CallableSelector.java:101)
    at org.jruby.java.dispatch.CallableSelector.matchingC allableArityN(CallableSelector.java:43)
    at org.jruby.java.invokers.RubyToJavaInvoker.findCall able(RubyToJavaInvoker.java:171)
    at org.jruby.java.invokers.InstanceMethodInvoker.call (InstanceMethodInvoker.java:28)
    at org.jruby.java.invokers.InstanceMethodInvoker.call (InstanceMethodInvoker.java:97)
    at org.jruby.runtime.callsite.SuperCallSite.cacheAndC all(SuperCallSite.java:286)
    at org.jruby.runtime.callsite.SuperCallSite.callBlock (SuperCallSite.java:70)
    at org.jruby.runtime.callsite.SuperCallSite.call(Supe rCallSite.java:75)
    at org.jruby.ast.ZSuperNode.interpret(ZSuperNode.java :101)
    at org.jruby.ast.CallOneArgNode.interpret(CallOneArgN ode.java:57)
    at org.jruby.ast.LocalAsgnNode.interpret(LocalAsgnNod e.java:123)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.ja va:104)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:7 1)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHO D(ASTInterpreter.java:75)
    at org.jruby.internal.runtime.methods.InterpretedMeth od.call(InterpretedMethod.java:147)
    at org.jruby.internal.runtime.methods.DefaultMethod.c all(DefaultMethod.java:163)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAn dCall(CachingCallSite.java:262)
    at org.jruby.runtime.callsite.CachingCallSite.call(Ca chingCallSite.java:105)
    at org.jruby.ast.CallNoArgNode.interpret(CallNoArgNod e.java:63)
    at org.jruby.ast.CallNoArgNode.interpret(CallNoArgNod e.java:63)
    at org.jruby.ast.CallNoArgNode.interpret(CallNoArgNod e.java:63)
    at org.jruby.ast.CallNoArgBlockNode.interpret(CallNoA rgBlockNode.java:60)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.ja va:104)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:7 1)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHO D(ASTInterpreter.java:75)
    at org.jruby.internal.runtime.methods.InterpretedMeth od.call(InterpretedMethod.java:147)
    at org.jruby.internal.runtime.methods.DefaultMethod.c all(DefaultMethod.java:163)
    at org.jruby.runtime.callsite.CachingCallSite.cacheAn dCall(CachingCallSite.java:262)
    at org.jruby.runtime.callsite.CachingCallSite.call(Ca chingCallSite.java:105)
    at org.jruby.ast.VCallNode.interpret(VCallNode.java:8 6)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.ja va:104)
    at org.jruby.ast.EvStrNode.interpret(EvStrNode.java:8 6)
    at org.jruby.ast.DNode.appendToString(DNode.java:56)
    at org.jruby.ast.DNode.buildDynamicString(DNode.java: 65)
    at org.jruby.ast.DNode.interpret(DNode.java:30)
    at org.jruby.ast.NewlineNode.interpret(NewlineNode.ja va:104)
    at org.jruby.ast.BlockNode.interpret(BlockNode.java:7 1)
    at org.jruby.evaluator.ASTInterpreter.INTERPRET_METHO D(ASTInterpreter.java:75)
    at org.jruby.internal.runtime.methods.InterpretedMeth od.call(InterpretedMethod.java:120)
    at org.jruby.internal.runtime.methods.InterpretedMeth od.call(InterpretedMethod.java:134)
    at org.jruby.internal.runtime.methods.DefaultMethod.c all(DefaultMethod.java:154)
    at org.jruby.RubyClass.finvoke(RubyClass.java:666)
    at org.jruby.javasupport.util.RuntimeHelpers.invoke(R untimeHelpers.java:557)
    at org.jruby.RubyBasicObject.callMethod(RubyBasicObje ct.java:366)
    at org.springframework.scripting.jruby.JRubyScriptUti ls$RubyObjectInvocationHandler.invoke(JRubyScriptU tils.java:181)
    at $Proxy0.getMessage(Unknown Source)
    at it.unimore.cesia.RubyRunner.main(RubyRunner.java:1 4)
    ... 6 more
    What am I doing wrong? There is some specific documentation for stored procedure from jruby?

    Thank you a lot!

    Francesco
    Last edited by cesco; Jun 22nd, 2011, 03:10 AM.

  • #2
    StoredProcedure with jruby - solved

    Now this way it works:

    Code:
    require 'java'
    
    include_class 'org.test.Messenger'
    
    java_import "org.springframework.jdbc.core.SqlOutParameter"
    java_import "org.springframework.jdbc.object.StoredProcedure"
    java_import "org.springframework.jdbc.core.RowMapper"
    
    java_import "java.sql.Types"
    
    java_import "java.util.HashMap"
    
    
    class RubyMessenger 
      include Messenger
    
      def setMessage(message)
       @@message = message
      end
    
      def setDataSource(data_source)
        @@data_source = data_source
      end
    
      def getMessage
        "<#{@@message}> at #{get_time}"
      end
     
      private 
      def get_time
        time_result = TimeStoredProcedure.new(@@data_source)
        time = time_result.my_execute
       time.first.last
     end
    
     class TimeStoredProcedure < StoredProcedure 
       def initialize(ds)      
         sql = "sysdate"
         super(ds, sql)
    #     setDataSource(ds)
         setFunction(true)
    #     setSql(sql)
         param = SqlOutParameter.new('date', java.sql.Types::DATE)
         declareParameter(param)
         compile
       end
    
       def my_execute
         puts "executing ..."
    #the 'sysdate' sproc has no input parameters, so an empty Map is supplied...
         empty = {}
         res = execute(empty.to_java)
       end
    
     end
    
    end
    
    RubyMessenger.new
    The problem was that it is not possibile to implicitely call the StoredProcedure constructor (it has to be called explicitely), and then the
    - setDataSource(ds)
    - setSql(sql)
    are useless, and I had to rename the execute to my_execute because if I had TimeStoredProcedure#execute, each call to execute was to TimeStoredProcedure (and not to StoredProcedure), and I was unable to reach StoredProcedure with super.execute (I had a parameter mismatch error).

    Hope it helps someone,

    Francesco

    Comment

    Working...
    X