So the services, references and properties are untyped right?

  ...ant

On 9/12/06, Jean-Sebastien Delfino <[EMAIL PROTECTED]> wrote:

ant elder wrote:
[snip]
> With the change in r442461 you say ComponentType files are now
> optional and
> the Ruby implementation now automatically creates a default
> serviceType and
> referenceTypes as needed. Could you  say a bit about how that works so
we
> can try and do the same for the Java runtime?
>
>   ...ant
>

The RubyCalculator sample under

http://svn.apache.org/repos/asf/incubator/tuscany/cpp/sca/samples/RubyCalculator/sample.calculator/
shows the programming model for Ruby, as implemented in the Tuscany/C++
Ruby extension:

- A client can get a proxy to a service with:
  require("libtuscany_sca_ruby")
and
  calculator = SCA::locateService("CalculatorComponent/CalculatorService")

- You then simply call a business method on "calculator", like this:
  x = calculator.add(1, 2)

- A Ruby component is implemented by either functions in a Ruby module
or a Ruby class, like this:
    <component name="CalculatorComponent">
        <implementation.ruby script="CalculatorImpl.rb"
class="CalculatorImpl"/>
    </component>

- Public attributes of a Ruby component implementation class can  be
wired to target services, like this:
class CalculatorImpl
  attr_writer :divideService

  def div(arg1, arg2)
    print "Ruby - CalculatorImpl.div\n"
    @divideService.divide(arg1, arg2)
  end
end

and in your composite file:
  <component name="CalculatorComponent">
    <implementation.ruby script="CalculatorImpl.rb"
class="CalculatorImpl"/>
    <reference
name="divideService">DivideComponent/DivideService</reference>
  </component>

- Public attributes of a Ruby component implementation class can be
configured as component properties, like this:
  class DivideImpl
   attr_writer :round

   def divide(arg1, arg2)
    res = arg1.to_f / arg2.to_f
    if @round then
      res = res.round
    end
    res
  end

and in your composite file:
  <component name="DivideComponent">
    <implementation.ruby script="DivideImpl.rb" class="DivideImpl"/>
    <property name="round">true</property>
  </component>

Lastly, you can write a componentType file for your Ruby component, but
you don't have to, the Ruby extension introspects Ruby component
implementation classes for you and binds public attributes to references
and properties.

The runtime extension uses the Ruby C API. The Ruby interpreter is
written in C with a nice API so it's a pretty good fit. I'm not sure how
much of the design you can transpose to JRuby, but here's a summary:

- The Tuscany C++ Ruby extension embeds the Ruby interpreter. This
allows the runtime to run a Ruby component from any other SCA component,
the Axis2 HTTP server or the Axis2 Apache mod when running behind the
HTTP server.

- The extension also acts as a Ruby extension library, to allow
standalone Ruby scripts to invoke SCA services.

- SCA::locateService is declared to Ruby as a module function in module
SCA. Again I am using the Ruby C API to declare the module and the
function.

- I am also using the Ruby C API to introspect each Ruby component
implementation class, find public setter methods, and the Ruby
attributes to SCA references and properties.

- SCA references are handled by a Ruby proxy class, defined by the
extension (written in C), which exposes a Ruby interface and dispatches
all calls to the C++ runtime to handle the SCA invocation.

- The extension currently handles the conversion of simple types between
Ruby and C types. I'll probably map DataObjects to Ruby strings for now
unless somebody is interested in implementing an SDO Ruby language
binding.

The code of the Tuscany/C++ Ruby extension is there:

http://svn.apache.org/repos/asf/incubator/tuscany/cpp/sca/runtime/extensions/ruby/


Hope this helps...

--
Jean-Sebastien


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]


Reply via email to