## 9 Orber Examples

### 9.1 A Tutorial on How to Create a Simple Service

#### 9.1.1 Interface Design

This example uses a very simple stack server. The specification contains two interfaces: the first is the Stack itself and the other is the StackFactory which is used to create new stacks. The specification is in the file `stack.idl`.

    #ifndef _STACK_IDL
    #define _STACK_IDL

    module StackModule {

      exception EmptyStack {};

      interface Stack {

        long pop() raises(StackModule::EmptyStack);

        void push(in long value);

        void empty();

      };

      interface StackFactory {

        StackModule::Stack create_stack();
        void destroy_stack(in StackModule::Stack s);

      };

    };

    #endif

#### 9.1.2 Generating Erlang Code

Run the IDL compiler on this file by calling the `ic:gen/1` function

            1> ic:gen("stack").

This will produce the client stub and server skeleton. Among other files a stack API module named `StackModule_Stack.erl` will be produced. This will produce among other files a stack API module called `StackModule_Stack.erl` which contains the client stub and the server skeleton.

#### 9.1.3 Implementation of Interface

After generating the API stubs and the server skeletons it is time to implement the servers and if no special options are sent to the IDL compiler the file name should be `<global interface name>_impl.erl`, in our case `StackModule_Stack_impl.erl`.

    %% StackModule_Stack_impl example file.

    -module('StackModule_Stack_impl').
    -include_lib("orber/include/corba.hrl").
    -include("StackModule.hrl").
    -export([pop/1, push/2, empty/1, init/1, terminate/2]).

    init(_Env) ->
        {ok, []}.

    terminate(_From, _Reason) ->
        ok.

    push(Stack, Val)  ->
        {reply, ok, [Val | Stack]}.

    pop([Val | Stack]) ->
        {reply, Val, Stack};
    pop([]) ->
        corba:raise(#'StackModule_EmptyStack'{}).

    empty(_) ->
        {reply, ok, []}.

We also have the factory interface which is used to create new stacks and that implementation is in the file `StackModule_StackFactory_impl.erl`.

    %% StackModule_StackFactory_impl example file.

    -module('StackModule_StackFactory_impl').
    -include_lib("orber/include/corba.hrl").
    -export([create_stack/1, destroy_stack/2, init/1, terminate/2]).

    init(_Env) ->
        {ok, []}.

    terminate(_From, _Reason) ->
        ok.

    create_stack(State)  ->
        %% Just a create we don't want a link.
        {reply, 'StackModule_Stack':oe_create(), State}.

    destroy_stack(State, Stack)  ->
        {reply, corba:dispose(Stack), State}.

To start the factory server one executes the function `StackModule_StackFactory:oe_create/0` which in this example is done in the module `stack_factory.erl` where the started service is also registered in the name service.

    %% stack_factory example file.

    -module('stack_factory').
    -include_lib("orber/include/corba.hrl").
    -include_lib("orber/COSS/CosNaming/CosNaming.hrl").
    -include_lib("orber/COSS/CosNaming/lname.hrl").

    -export([start/0]).

    start() ->
        SFok = 'StackModule_StackFactory':oe_create(),
        NS = corba:resolve_initial_references("NameService"),
        NC = lname_component:set_id(lname_component:create(), "StackFactory"),
        N = lname:insert_component(lname:create(), 1, NC),
        'CosNaming_NamingContext':bind(NS, N, SFok).

#### 9.1.4 Writing a Client in Erlang

At last we will write a client to access our service.

    %% stack_client example file.

    -module('stack_client').

    -export([run/0]).

    run() ->
        case catch corba:string_to_object("corbaname:rir:/NameService#StackFactory") of
            {'EXCEPTION', _E} ->
                io:format("The stack factory server is not registered~n",[]);
            SF ->
                %% Create the stack
                SS = 'StackModule_StackFactory':create_stack(SF),

                'StackModule_Stack':push(SS, 4),
                'StackModule_Stack':push(SS, 7),
                'StackModule_Stack':push(SS, 1),
                'StackModule_Stack':push(SS, 1),
                Res = 'StackModule_Stack':pop(SS),
                io:format("~w~n", [Res]),
                Res1 = 'StackModule_Stack':pop(SS),
                io:format("~w~n", [Res1]),
                Res2 = 'StackModule_Stack':pop(SS),
                io:format("~w~n", [Res2]),
                Res3 = 'StackModule_Stack':pop(SS),
                io:format("~w~n", [Res3]),

                %% Remove the stack
                'StackModule_StackFactory':destroy_stack(SF, SS)

        end.

#### 9.1.5 Writing a Client in Java

To write a Java client for Orber you must have another ORB that uses IIOP for client-server communication and supports a Java language mapping. It must also have support for `IDL:CosNaming/NamingContext` or `IDL:CosNaming/NamingContextExt`. If the client ORB support Interoperable Naming Service the Java Client can look like:

    /*
     * Stack example.
     */

    package StackModule;
    import org.omg.CORBA.*;
    import org.omg.CORBA.SystemException;
    import org.omg.CORBA.ORB.*;

    public class StackClient
    {
      public static void main(String args[])
        {
          org.omg.CORBA.Object objRef;
          StackFactory sfRef = null;
          Stack sRef = null;
          // The argument can look like
          // "corbaname::host:4001/#StackFactory"
          String corbaName = new String(args[0]);
          try{
              ORB orb = ORB.init(args, null);

              objRef = orb.string_to_object(corbaName);
              sfRef  = StackFactoryHelper.narrow(objRef);
              sRef   = sfRef.create_stack();

              sRef.push(4);
              sRef.push(7);
              sRef.push(1);
              sRef.push(1);

              try{
                  System.out.println(sRef.pop());
                  System.out.println(sRef.pop());
                  System.out.println(sRef.pop());
                  System.out.println(sRef.pop());
                  // The following operation shall
                  // return an EmptyStack exception
                  System.out.println(sRef.pop());
                }
              catch(EmptyStack es) {
                  System.out.println("Empty stack");
                };

              sfRef.destroy_stack(sRef);
            }
         catch(SystemException se)
           {
             System.out.println("Unexpected exception: " + se.toString());
             return;
           }
        }
    }

| If an ORB does not support CosNaming at all the `cos_naming.idl` file must be compiled and imported.

#### 9.1.6 Building the Example

To build the example for access from a Java client you need a Java enabled ORB (e.g. JavaIDL). The example below is based on JDK-1.4.

    fingolfin 127> erl
    Erlang (BEAM) emulator version 5.5.4.3 [async-threads:0] [hipe] [kernel-poll:false]

    Eshell V5.5.4.3  (abort with ^G)
    1> ic:gen(stack).
    Erlang IDL compiler version 4.2.12
    ok
    2> make:all().
    Recompile: StackModule_EmptyStack
    Recompile: StackModule_Stack
    Recompile: StackModule_StackFactory
    Recompile: StackModule_StackFactory_impl
    Recompile: StackModule_Stack_impl
    Recompile: oe_stack
    Recompile: stack_client
    Recompile: stack_factory
    up_to_date
    3>
    BREAK: (a)bort (c)ontinue (p)roc info (i)nfo (l)oaded
           (v)ersion (k)ill (D)b-tables (d)istribution
    a
    fingolfin 128> idlj stack.idl
    fingolfin 129> javac StackModule/*.java
    fingolfin 130> javac *.java
    fingolfin 131> cp StackClient.class StackModule/

#### 9.1.7 How to Run Everything

Below is a short transcript on how to run Orber.

    fingolfin 143> erl
    Erlang (BEAM) emulator version 5.5.4.3 [async-threads:0] [hipe] [kernel-poll:false]

    Eshell V5.5.4.3  (abort with ^G)
    1> orber:jump_start([{interceptors, {native, [orber_iiop_tracer_silent]}}]).
    ok
    2> oe_stack:oe_register().
    ok
    3> stack_factory:start().
    ok
    4> stack_client:run().
    1
    1
    7
    4
    ok
    5>

Before testing the Java part of this example generate and compile Java classes for `orber/examples/stack.idl` as seen in the build example. To run the Java client use the following command:

    fingolfin 38> java StackModule.StackClient "corbaname::localhost:4001#StackFactory"
    1
    1
    7
    4
    Empty stack
    fingolfin 39>

### 9.2 A Tutorial on How to Start Orber as Lightweight

#### 9.2.1 Preparation

When starting Erlang the configuration parameter `lightweight` must be used. The value is set to a list of remote modifiers, equal to the `orber:resolve_initial_references_remote/2` argument, i.e., "iiop://host:port". On these given nodes, all necessary `oe_X:oe_register()` calls must be done before running a Orber lightweight.

Lightweight Orber do not allow us to:

- Create objects locally
- Accept incoming requests
- Access local NameService
- Register data in the IFR

With lightweight Orber we do not:

- Start Mnesia
- Run `orber:install/1`

To be able to start objects we must supply a factory on a non-lightweight node(s) which can start necessary objects. One way to accomplish this is:

    smaug 125> erl -orber domain "ORBER_MAIN"
    Erlang (BEAM) emulator version 4.9

    Eshell V4.9    (abort with ^G)
    1> mnesia:create_schema([]).
    2> orber:install([]).
    3> orber:start().
    4> oe_MyFactory:oe_register().
    5> oe_MyObjects:oe_register().  %% Do this for all objects necessary.
    6> Factory=MyFactory_Creater:oe_create().
    7> NS=orber:resolve_initial_references("NameService").
    8> NC=lname_component:set_id(lname_component:create(), "myFactory").
    9> N =lname:insert_component(lname:create(), 1, NC).
    10> 'CosNaming_NamingContext':bind(NS, N, Factory)).

Now we have a factory we can access from, hence, we can now start a lightweight Orber:

    fingolfin 14> erl -orber lightweight [\"iiop://host1:port\",
                                          \"iiop://host2:port\"]
                      -orber domain \"ORBER_LIGHT\"
    Erlang (BEAM) emulator version 4.9

    Eshell V4.9    (abort with ^G)
    1> orber:start_lightweight().
    2> Fac=corba:string_to_object("corbaname::Host:Port/NameService#myFactory"),
    3> Obj=MyFactory_Creater:MyObject(Fac, Args).
    4> MyObject:myFunction(Obj,Args2).

It is not necessary to start both Orber types using the configuration parameter `domain`, but at least one of them.

orber 3.6.6
Copyright © 1991-2007 Ericsson AB