#### 6.6.1 `echo` example

We consider building a simple “Echo” CORBA server and client. This application echoes a string. The source code for this example is located in the `examples/corba/echo` directory in the PolyORB distribution. This applications uses only basic elements of CORBA.

To build this application, you need the following pieces of code:

1. IDL definition of an `echo` object
2. Implementation code for the `echo` object
3. Code for client and server nodes

#### 6.6.1.1 IDL definition of an `echo` object

This interface defines an `echo` object with a unique method `echoString`. Per construction, this method returns its argument.

    interface Echo {
      string echoString (in string Mesg);
    };

#### 6.6.1.2 Implementation code for the `echo` object

Package `Echo.Impl` is an implementation of this interface. This implementation follows the IDL-to-Ada mapping.

    ------------------------------------------------------------------------------
    --                                                                          --
    --                           POLYORB COMPONENTS                             --
    --                                                                          --
    --                            E C H O . I M P L                             --
    --                                                                          --
    --                                 S p e c                                  --
    --                                                                          --
    --         Copyright (C) 2002-2012, Free Software Foundation, Inc.          --
    --                                                                          --
    -- This is free software;  you can redistribute it  and/or modify it  under --
    -- terms of the  GNU General Public License as published  by the Free Soft- --
    -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
    -- sion.  This software is distributed in the hope  that it will be useful, --
    -- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
    -- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public --
    -- License for  more details.                                               --
    --                                                                          --
    -- You should have received a copy of the GNU General Public License and    --
    -- a copy of the GCC Runtime Library Exception along with this program;     --
    -- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
    -- <http://www.gnu.org/licenses/>.                                          --
    --                                                                          --
    --                  PolyORB is maintained by AdaCore                        --
    --                     (email: sales@adacore.com)                           --
    --                                                                          --
    ------------------------------------------------------------------------------

    with CORBA;
    with PortableServer;

    package Echo.Impl is

       --  My own implementation of echo object.
       --  This is simply used to define the operations.

       type Object is new PortableServer.Servant_Base with null record;

       type Object_Acc is access Object;

       function EchoString
         (Self : access Object;
          Mesg : CORBA.String)
         return CORBA.String;

    end Echo.Impl;

    ------------------------------------------------------------------------------
    --                                                                          --
    --                           POLYORB COMPONENTS                             --
    --                                                                          --
    --                            E C H O . I M P L                             --
    --                                                                          --
    --                                 B o d y                                  --
    --                                                                          --
    --         Copyright (C) 2002-2012, Free Software Foundation, Inc.          --
    --                                                                          --
    -- This is free software;  you can redistribute it  and/or modify it  under --
    -- terms of the  GNU General Public License as published  by the Free Soft- --
    -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
    -- sion.  This software is distributed in the hope  that it will be useful, --
    -- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
    -- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public --
    -- License for  more details.                                               --
    --                                                                          --
    -- You should have received a copy of the GNU General Public License and    --
    -- a copy of the GCC Runtime Library Exception along with this program;     --
    -- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
    -- <http://www.gnu.org/licenses/>.                                          --
    --                                                                          --
    --                  PolyORB is maintained by AdaCore                        --
    --                     (email: sales@adacore.com)                           --
    --                                                                          --
    ------------------------------------------------------------------------------

    with Ada.Text_IO;

    with Echo.Skel;
    pragma Warnings (Off, Echo.Skel);
    --  No entity from Echo.Skel is referenced.

    package body Echo.Impl is

       ----------------
       -- EchoString --
       ----------------

       function EchoString
         (Self : access Object;
          Mesg : CORBA.String)
         return CORBA.String
       is
          pragma Warnings (Off);
          pragma Unreferenced (Self);
          pragma Warnings (On);

          S : String := CORBA.To_Standard_String (Mesg);
          L : Natural := S'Last;
       begin
          if S'Length > 13 then
             L := S'First + 12;
             S (L - 2 .. L) := (others => '.');
          end if;
          Ada.Text_IO.Put_Line
            ("Echoing string: « " & S (S'First .. L) & " »");
          return Mesg;
       end EchoString;

    end Echo.Impl;

Note: `Echo.Impl` body requires a dependency on `Echo.Skel` to ensure the elaboration of skeleton code and the correct setup of PolyORB’s internals.

#### 6.6.1.3 Test code for client and server nodes

Client and server code demonstrate how to make a remote invocation on a CORBA object, and how to set up an object on a server node.

Note: the dependency on `PolyORB.Setup.Client` or `PolyORB.Setup.No_Tasking_Server` enforces compile-time configuration, see Sample files.

- Client code tests a simple remote invocation on an object. It is a no-tasking client. A reference to the object is built from a stringified reference (or `IOR`), which is passed on command line.

      ------------------------------------------------------------------------------
      --                                                                          --
      --                           POLYORB COMPONENTS                             --
      --                                                                          --
      --                               C L I E N T                                --
      --                                                                          --
      --                                 B o d y                                  --
      --                                                                          --
      --         Copyright (C) 2002-2012, Free Software Foundation, Inc.          --
      --                                                                          --
      -- This is free software;  you can redistribute it  and/or modify it  under --
      -- terms of the  GNU General Public License as published  by the Free Soft- --
      -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
      -- sion.  This software is distributed in the hope  that it will be useful, --
      -- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
      -- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public --
      -- License for  more details.                                               --
      --                                                                          --
      -- You should have received a copy of the GNU General Public License and    --
      -- a copy of the GCC Runtime Library Exception along with this program;     --
      -- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
      -- <http://www.gnu.org/licenses/>.                                          --
      --                                                                          --
      --                  PolyORB is maintained by AdaCore                        --
      --                     (email: sales@adacore.com)                           --
      --                                                                          --
      ------------------------------------------------------------------------------

      --  Echo client

      with Ada.Command_Line;
      with Ada.Text_IO;
      with CORBA.ORB;

      with Echo;

      with PolyORB.Setup.Client;
      pragma Warnings (Off, PolyORB.Setup.Client);

      with PolyORB.Utils.Report;

      procedure Client is
         use Ada.Command_Line;
         use Ada.Text_IO;
         use PolyORB.Utils.Report;
         use type CORBA.String;

         Sent_Msg, Rcvd_Msg : CORBA.String;
         myecho : Echo.Ref;

         Length : Natural := 0;
         Calls  : Natural := 1;
      begin
         New_Test ("Echo client");

         CORBA.ORB.Initialize ("ORB");
         if Argument_Count not in 1 .. 3 then
            Put_Line
              ("usage: client <IOR_string_from_server>|-i [strlen [num of calls]]");
            return;
         end if;

         --  Getting the CORBA.Object

         CORBA.ORB.String_To_Object
           (CORBA.To_CORBA_String (Ada.Command_Line.Argument (1)), myecho);

         --  Get optional arguments Length and Calls

         if Argument_Count >= 2 then
            Length := Natural'Value (Ada.Command_Line.Argument (2));
         end if;

         if Argument_Count >= 3 then
            Calls := Natural'Value (Ada.Command_Line.Argument (3));
         end if;

         --  Checking if it worked

         if Echo.Is_Nil (myecho) then
            Put_Line ("main : cannot invoke on a nil reference");
            return;
         end if;

         --  Sending message

         if Length = 0 then
            Sent_Msg := CORBA.To_CORBA_String (Standard.String'("Hello Ada !"));
         else
            Sent_Msg := CORBA.To_CORBA_String
                          (Standard.String'(1 .. Length => 'X'));
         end if;

         for J in 1 .. Calls loop
            Rcvd_Msg := Echo.echoString (myecho, Sent_Msg);
         end loop;

         if Rcvd_Msg /= Sent_Msg then
            raise Program_Error with "incorrect string returned by server";
         end if;

         --  Printing result

         if Length = 0 then
            Put_Line ("I said : " & CORBA.To_Standard_String (Sent_Msg));
            Put_Line
              ("The object answered : " & CORBA.To_Standard_String (Rcvd_Msg));

         else
            Put_Line ("I said : 'X' *" & Length'Img);
            Put_Line ("The object answered the same.");
         end if;

         End_Report;

      exception
         when E : CORBA.Transient =>
            Output ("echo test", False);
            declare
               Memb : CORBA.System_Exception_Members;
            begin
               CORBA.Get_Members (E, Memb);
               Put ("received exception transient, minor");
               Put (CORBA.Unsigned_Long'Image (Memb.Minor));
               Put (", completion status: ");
               Put_Line (CORBA.Completion_Status'Image (Memb.Completed));

               End_Report;
            end;
      end Client;

- The server code sets up a no-tasking node. The object is registered to the `RootPOA`. Then an `IOR` reference is built to enable interaction with other nodes.

      ------------------------------------------------------------------------------
      --                                                                          --
      --                           POLYORB COMPONENTS                             --
      --                                                                          --
      --                               S E R V E R                                --
      --                                                                          --
      --                                 B o d y                                  --
      --                                                                          --
      --         Copyright (C) 2002-2012, Free Software Foundation, Inc.          --
      --                                                                          --
      -- This is free software;  you can redistribute it  and/or modify it  under --
      -- terms of the  GNU General Public License as published  by the Free Soft- --
      -- ware  Foundation;  either version 3,  or (at your option) any later ver- --
      -- sion.  This software is distributed in the hope  that it will be useful, --
      -- but WITHOUT ANY WARRANTY;  without even the implied warranty of MERCHAN- --
      -- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public --
      -- License for  more details.                                               --
      --                                                                          --
      -- You should have received a copy of the GNU General Public License and    --
      -- a copy of the GCC Runtime Library Exception along with this program;     --
      -- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
      -- <http://www.gnu.org/licenses/>.                                          --
      --                                                                          --
      --                  PolyORB is maintained by AdaCore                        --
      --                     (email: sales@adacore.com)                           --
      --                                                                          --
      ------------------------------------------------------------------------------

      with Ada.Exceptions;
      with Ada.Text_IO; use Ada.Text_IO;

      with CORBA.Impl;
      with CORBA.Object;
      with CORBA.ORB;

      with PortableServer.POA.Helper;
      with PortableServer.POAManager;

      with Echo.Impl;

      with PolyORB.CORBA_P.CORBALOC;

      --  Setup server node: use no tasking default configuration

      with PolyORB.Setup.No_Tasking_Server;
      pragma Warnings (Off, PolyORB.Setup.No_Tasking_Server);

      procedure Server is
      begin

         declare
            Argv : CORBA.ORB.Arg_List := CORBA.ORB.Command_Line_Arguments;

         begin
            CORBA.ORB.Init (CORBA.ORB.To_CORBA_String ("ORB"), Argv);

            declare
               Root_POA : PortableServer.POA.Local_Ref;

               Ref : CORBA.Object.Ref;

               Obj : constant CORBA.Impl.Object_Ptr := new Echo.Impl.Object;

            begin

               --  Retrieve Root POA

               Root_POA := PortableServer.POA.Helper.To_Local_Ref
                 (CORBA.ORB.Resolve_Initial_References
                  (CORBA.ORB.To_CORBA_String ("RootPOA")));

               PortableServer.POAManager.Activate
                 (PortableServer.POA.Get_The_POAManager (Root_POA));

               --  Set up new object

               Ref := PortableServer.POA.Servant_To_Reference
                 (Root_POA, PortableServer.Servant (Obj));

               --  Output IOR

               Put_Line
                 ("'"
                  & CORBA.To_Standard_String (CORBA.Object.Object_To_String (Ref))
                  & "'");
               New_Line;

               --  Output corbaloc

               Put_Line
                 ("'"
                  & CORBA.To_Standard_String
                  (PolyORB.CORBA_P.CORBALOC.Object_To_Corbaloc (Ref))
                  & "'");

               --  Launch the server. CORBA.ORB.Run is supposed to never return,
               --  print a message if it does.

               CORBA.ORB.Run;

               Put_Line ("ORB main loop terminated!");
            end;
         end;
      exception
         when E : others =>
            Put_Line
              ("Echo server raised " & Ada.Exceptions.Exception_Information (E));
            raise;
      end Server;

#### 6.6.1.4 Compilation and execution

To compile this demo,

1. Process the IDL file with `idlac` (or `iac`)

        $ idlac echo.idl

2. Compile the client node

        $ gnatmake client.adb `polyorb-config`

3. Compile the server node

        $ gnatmake server.adb `polyorb-config`

Note the use of backticks (‘). This means that `polyorb-config` is first executed, and then the command line is replaced with the output of the script, setting up library and include paths and library names.

To run this demo:

- run `server`, the server outputs its IOR, a hexadecimal string with the IOR: prefix:

      $ ./server
      Loading configuration from polyorb.conf
      No polyorb.conf configuration file.
      'IOR:01534f410d00000049444c3[..]'

- In another shell, run `client`, passing cut-and-pasting the complete IOR on the command line:

      $ ./client 'IOR:01534f410d00000049444c3[..]'
      Echoing string: " Hello Ada ! "
      I said : Hello Ada !
      The object answered : Hello Ada !