Tutorial requirements  Chapter 4: Creating Enterprise JavaBeans Components and Clients

Chapter 3: Creating C++ Components and Clients

Creating the application

To create and run the sample application:

  1. Verify your environment.

  2. Start EAServer and EAServer Manager.

  3. Define a package, component, and method.

  4. Generate stubs, skeletons, and implementation templates.

  5. Write the server-side code.

  6. Write the client-side code.

  7. Compile the client executable.

  8. Run the client executable.


Verify your environment

Before running the tutorial, verify these environment settings:

StepsConfiguring the Windows environment

  1. To configure the command line where you are running the tutorials, run these commands, substituting your EAServer installation location for eas-home:

    set JAGUAR=eas-home
    set PATH=%JAGUAR%\dll;%PATH%
    

    You can also edit these variables in the System dialog for the Windows Control Panel, or create a batch file to configure the settings.

StepsConfiguring the UNIX environment for C shell

  1. To configure the C shell session where you are running the tutorials, run these commands, substituting your EAServer installation location for eas-home, and the shared-library variable from Table 3-1 for LIB_PATH:

    setenv JAGUAR eas-home
    setenv LIB_PATH $JAGUAR/lib:$LIB_PATH
    

    If running on Solaris, using a version 4.x CC compiler:

    setenv JAGUAR eas-home
    setenv LD_LIBRARY_PATH \
    $JAGUAR/lib_sol4x:$LD_LIBRARY_PATH
    

StepsConfiguring the UNIX environment for Bourne shell

  1. To configure the Bourne shell session where you are running the tutorials, run these commands, substituting your EAServer installation location for eas-home, and the shared-library variable from Table 3-1 for LIB_PATH:

    JAGUAR=eas-home export JAGUAR
    LIB_PATH=$JAGUAR/lib:$LIB_PATH export LIB_PATH
    

    If running on Solaris, using a version 4.x CC compiler:

    JAGUAR=eas-home export JAGUAR
    LD_LIBRARY_PATH=$JAGUAR/lib_sol4x:$LD_LIBRARY_PATH export LD_LIBRARY_PATH
    

Start EAServer and EAServer Manager

StepsStarting the server

  1. If the server is not already running, follow the instructions under “Starting the server”.

StepsStarting EAServer Manager

  1. If EAServer Manager is not already running, start it as described in “Using EAServer Manager”.


Define a package, component, and method

This section shows you how to use EAServer Manager to create the package, component, and method for the sample application.

For complete information on configuring packages, components, and methods, see Chapter 5, “Defining Component Interfaces,” in the EAServer Programmer’s Guide.


Define a new package

In EAServer, a package is a unit of deployment for a group of components that perform related tasks. All components created in the EAServer tutorials are installed in the Tutorial package.

Before a component can be instantiated by clients, it must be installed in a package, and that package must be installed in the server. The steps below create the package and component within the predefined “Jaguar” server to satisfy these requirements.

StepsCreating the Tutorial package if it does not exist

  1. In EAServer Manager, expand the servers folder, then expand the Jaguar server icon.

  2. Expand the Installed Packages folder. If the Tutorial package is displayed, skip to “Define and install a new component”.

  3. Highlight the Installed Packages folder, and select File | Install Package.

    In the Package wizard, select Create and Install a New Package.

    For the package name, enter Tutorial.

  4. Click Create New Package.

    You see the Package Properties window.

  5. Click OK.


Define and install a new component

You will define a new C++ component, CPPArithmetic.

StepsDefining the component

  1. Click on the Tutorial package.

  2. Select File | New Component.

  3. In the New Component wizard, select Define New Component.

    For the component name, enter CPPArithmetic.

  4. Click Finish.

    You see the Component Properties window.

  5. Select the General tab. Fill in the fields as follows:

    Field

    Value

    Description

    Tutorial C++ component

    Codeset

    Server’s Codeset (default)

    Component Type

    C++

    DLL Name

    libCPPArithmetic (no extension)

    C++ Class

    CPPArithmeticImpl

    C++ Executable

    (blank)

    Use Platform Independent Naming

    Unchecked

  6. Leave the remaining fields at their default settings.

  7. Click OK.


Define the multiply method

The component interface will have one method, multiply.

StepsDefining the component interface

  1. Expand the Tutorial package. Double-click the CPPArithmetic component to show the Roles and Interfaces folders beneath it.

  2. Double-click the Interfaces folder, and highlight the Tutorial::CPPArithmetic interface. If you do not see this interface, install it as follows:

    1. Highlight the Interfaces folder and select File | Add Interfaces ...

    2. In the Install Interface dialog box, highlight Tutorial::CPPArithmetic in the Selected to Install table, then click Install.

    3. Highlight the Tutorial::CPPArithmetic interface that is now displayed under the Interfaces folder.

  3. With the Tutorial::CPPArithmetic interface highlighted, select File | New Method.

  4. Assign the name multiply to the method.

  5. Click Create New Method.

    You see the Method Properties window.

  6. In the Return field, select double as the method’s return type.

  7. Beneath the empty parameter list, click Add to add a parameter. In the New Parameter dialog:

  8. Click OK to close the New Parameter dialog box.

  9. Repeat steps 7 and 8 to add a second parameter named m2 with a Type of double.

  10. Click OK to close the Method Properties dialog box.


Generate stubs, skeletons, and implementation templates

Once you have created the package, component, and methods, you can generate the stub and skeleton files for the component. The client executable uses the stubs to invoke the server-side component methods. The server uses the skeleton to invoke your component implementation class.

StepsGenerating the stubs and skeletons

  1. Click on the Tutorial package and select the CPPArithmetic component.

  2. Select File | Generate Stubs/Skeletons.

  3. Deselect Generate Java Stubs.

  4. Select Generate Stubs, then check C++ Stubs. Leave the C/C++ Code Base field at the default setting, which should be the full path to your EAServer include subdirectory.

  5. Click Next to display the skeleton generation options, and select Generate Skeletons.

  6. Under Skeletons, select Generate Skeletons on Client and leave the C/C++ Code Base field at the default setting, which should be the full path to your EAServer cpplib subdirectory.

  7. Click Finish.


Write the server-side code

EAServer Manager has generated C++ implementation templates for the component methods. Here we will fill in the implementation template, then build a shared library or DLL file. Finally, we will verify that the shared library or DLL is in the EAServer cpplib subdirectory, where EAServer expects to find C and C++ component library files.

StepsWriting the server-side code

  1. Navigate to the cpplib directory under your EAServer installation, then navigate to the Tutorial/CPPArithmetic subdirectory. You should see the following files:

  2. Rename the implementation files to CPPArithmeticImpl.hpp and CPPArithmeticImpl.cpp. (In other words, remove the .new extension from both file names).

  3. Open CPPArithmeticImpl.cpp in a text editor, then find the definition of the multiply method. Change the definition so that it matches the one below:

    CORBA::Double CPPArithmeticImpl::multiply
        (CORBA::Double m1,
        CORBA::Double m2)
    {
        CORBA::Double result;
        result = m1 * m2;
        return result;
    }
    
  4. Save your changes.

StepsBuilding the component on Windows

  1. Verify your setup as described in “Verify your environment”.

  2. Rename make.nt to Makefile, then open Makefile in a text editor. Find the definition of the ODBCHOME macro:

    ODBCHOME=d:\msdev
    
  3. Change the ODBCHOME definition to match the directory where you have installed Microsoft Visual C++, for example:

    ODBCHOME="D:\engapps\devStudio\VC98"
    
  4. Save your changes.

  5. Build the DLL by running nmake (no arguments are required).

You should see a new file called libCPPArithmetic.dll. Verify that the makefile has copied this file to the EAServer cpplib subdirectory. If nmake fails, verify that you have renamed the .cpp and .hpp implementation files with the expected file names, and that you have applied the correct edits to CPPArithmeticImpl.cpp and Makefile.

StepsBuilding the component on UNIX platforms

  1. Verify your setup as described in “Verify your environment”.

  2. Rename make.unix to Makefile.

  3. On Solaris, the make file is compatible with the Solaris CC compiler, version 6.x. If you use a version 4.x compiler, edit Makefile and change -L$JAGUAR/lib to -L$JAGUAR/lib_sol4x. You must use the compiler version that is compatible with your server. The default server binary requires libraries compatible with the 6.x compiler, but you can override this setting when starting the server. For more information, see “Starting the server” in the EAServer System Administration Guide.

  4. Build the shared library by running make (no arguments are required).

You should see a new file called libCPPArithmetic.ext, where ext is the appropriate shared library extension for your platform. Verify that the makefile has copied this file to the EAServer cpplib subdirectory.

If make fails, verify the following:


Write the client-side code

Create the source file for the sample C++ client, arith.cpp. You can find a copy of arith.cpp in the html/docs/tutorial/cpp subdirectory of your EAServer installation. Here is the source for arith.cpp:

/*
** arith.cpp -- Example C++ client for the EAServer C++
**   tutorial.
**
**   This program connects to EAServer,
**   creates an instance of the Tutorial/CPPArithmetic 
**   component, and invokes the multiply method.
**
** Usage:
**    arith iiop://<host>:<port>
**
**    Where:
**
**       <host> is the host name or IP address of the server machine. 
**
**       <iiop-port> is the server's IIOP port (9000 in the
**         default configuration).
**
*/

#include <stdio.h>
#include <iostream.h>
#include <string.h>
#include <Jaguar.hpp>
#include <SessionManager.hpp>
#include <Tutorial.hpp>    // Stubs for interfaces in Tutorial IDL 
                           // module.

int main(int argc, char** argv)
{
    const char *usage = 
"Usage:\n\tarith iiop://<host>:<iiop-port>\n";
    const char *tutorial_help =
"Check Jaguar Manager and verify that the"
"Tutorial/CPPArithmetic component exists "
"and that it implements the "
"Tutorial::CPPArithmetic IDL interface.";

    const char *component_name = "Tutorial/CPPArithmetic";

    try {

        if (argc < 2) 
        {
          cout << usage;
          return -1;
        }

        char* manager_url = argv[1];

        cout << "**** Creating session\n";

        // Initialize the ORB
        CORBA::ORB_var orb = CORBA::ORB_init(argc, argv, 0);

       // Create a SessionManager::Manager instance
       
       CORBA::Object_var obj = 
           orb->string_to_object(manager_url);
       SessionManager::Manager_var manager = 
         SessionManager::Manager::_narrow(obj);
        if (CORBA::is_nil(manager)) 
        {
           cout << "Error: Null SessionManager::Manager instance. Exiting. "
                << usage ;
           return -1;
        }

        // Create an authenticated session for user Guest
        // using password GuestPassword

        SessionManager::Session_var session = 
          manager->createSession("Guest", "GuestPassword");
        if (CORBA::is_nil(session)) 
        {
          cout << "Error: Null session. Exiting. " << usage;
          return -1;
        }

        // Obtain a factory for component instances by 
        // resolving the component name

        cout << "**** Creating component instance for " 
             << component_name << "\n" ;

        obj = session->lookup(component_name);
        SessionManager::Factory_var arithFactory = 
        SessionManager::Factory::_narrow(obj);

        if (CORBA::is_nil(arithFactory)) 
        {
           cout << "ERROR: Null component factory for component " 
                 << component_name 
                 << tutorial_help ;
            return -1;
        }

       // Use the factory to create an instance.

        Tutorial::CPPArithmetic_var arith = 
           Tutorial::CPPArithmetic::_narrow(arithFactory->create());

        // Verify that we really have an instance.
        if (CORBA::is_nil(arith)) {
            cout << "ERROR: Null component instance. "
                 << tutorial_help ;
            return -1;
        }


        // Call the multiply method.

        cout << "**** Multiplying ...\n\n";
        CORBA::Double m1 = (CORBA::Double)3.1;
        CORBA::Double m2 = (CORBA::Double)2.5;
        CORBA::Double result = arith->multiply(m1, m2);

        cout << (double)m1 << " * " << (double)m2 
             << " = " << (double)result
             << "\n\n";

    }
    
    // Explicitly catch exceptions that can occur due to user error,
    // and print a generic error message for any other CORBA system 
    // exception.

    // Requested object (component) does not exist.
    catch ( CORBA::OBJECT_NOT_EXIST cone )
    {
        cout << "Error: CORBA OBJECT_NOT_EXIST exception. Check the "
             << "server log file for more information. Also verify "
             << "that the " << component_name 
             << " component has been created properly in "
             << "Jaguar Manager. " << tutorial_help ;
    }

    // Authentication or authorization failure.
    catch ( CORBA::NO_PERMISSION npe )
    {
        cout << "Error: CORBA:: NO_PERMISSION exception. Check whether "
             << "login authentication is enabled for your server and "
             << "whether the component has restricted access. If so "
             << "edit the source file to use a valid user name and "
             << "password.\n";
    }

    // Invalid object reference.
    catch ( CORBA::INV_OBJREF cio ) 
    {
        cout << "Error: CORBA INV_OBJREF exception.";
    }

    // Communication failure. Server could be down or URL's port value
    // could be wrong.
    catch ( CORBA::COMM_FAILURE ccf ) 
    {
        cout << "Error: CORBA COMM_FAILURE exception. Check that the "
             << "specified host and IIOP port number are "
             << "correct and that the server is running. "
             << usage;
    }

    // Anything else.
    catch ( CORBA::OBJ_ADAPTER ) 
    {
        cout << "Error: CORBA::OBJ_ADAPTER \n";
    }
    catch ( CORBA::SystemException cse ) 
    {
        cout << "Error: CORBA System Exception. Check that the server "
             << "hostname and IIOP port are specified correctly, and "
             << "check the server's error log for more information.\n"
             << usage; 
    }

    return 0;
}

Compile the client executable

StepsCompiling the client on Windows

  1. Verify your setup as described in “Verify your environment”.

  2. Create a batch file with these commands and run it:

    SETLOCAL
    call %JAGUAR%\bin\setenv.bat
    set INCLUDE=.;%JAGUAR%\include;%INCLUDE%;
    set INCLUDE=%INCLUDE%;%JAGUAR_JDK13%\include;
    set INCLUDE=%INCLUDE%;%JAGUAR_JDK13%\include\win32
    set LIB=%JAGUAR%\lib;%LIB%
    cl /W3 /nologo /DWIN32 /Gd /GX -c arith.cpp
    set SYSLIBS=kernel32.lib advapi32.lib
    link /MAP /out:arith.exe arith.obj libjcc.lib libjutils.lib %SYSLIBS%
    ENDLOCAL
    

StepsCompiling the client on UNIX

  1. Verify your setup as described in “Verify your environment”.

  2. Create a shell script containing the commands for your platform from Table 3-2, then run the shell script.

  3. Change the script file permissions to allow execution, for example, assuming you have named the script compile.sh:

    chmod 777 compile.sh
    
    Table 3-2: Client compilation commands for UNIX platforms

    Platform

    Shell script

    Solaris

    This shell script works with the Solaris CC compiler, version 6.x:

    #!/bin/sh
    . $JAGUAR/bin/setenv.sh
    CC -DJAG_NO_NAMESPACE -z muldefs -I. -I$JAGUAR/include \
    -I$JAGUAR_JDK13/include -I$JAGUAR_JDK13/include/solaris \
    -L$JAGUAR/lib -ljcc -ljtml_r -ljtli_r -lunic -lnsl \
    -ldl -lthread -lm -ljutils -o arith arith.cpp
    

    If you use the version 4.x compiler, change -L$JAGUAR/lib to -L$JAGUAR/lib_sol4x.

    HP-UX

    This shell script uses the HP-UX ANSI C++ (aCC) compiler:

    #!/bin/sh
    . $JAGUAR/bin/setenv.sh
    aCC -c  +DA1.1 +DS2.0 +u4 -DNATIVE -D_HPUX -D_POSIX_C_SOURCE=199506L \
      -D_HPUX_SOURCE  -I $(JAGUAR_JDK13)/include -I $(JAGUAR_JDK13)/include/hp-ux \
      -I $(JAGUAR_JDK12)/include -I $(JAGUAR_JDK12)/include/hp-ux  -I. \
      -I$JAGUAR/include -L$JAGUAR/lib -lpthread -ljcc -lnsl -ljtml_r \
      -ljinsck_r -lunic -ljutils -o arith arith.cpp 
    

    HP Itanium

    This shell script uses the HP C++ (aCC) compiler:

    #!/bin/sh
    . $JAGUAR/bin/setenv.sh
    
    aCC -g +DD32 -mt -I$(JAGUAR_JDK13)/include -I$(JAGUAR_JDK13)/include/hp-ux \
    -I$(JAGUAR_JDK14)/include -I$(JAGUAR_JDK14)/include/hp-ux -I. \
    -I$(JAGUAR)/include -L$(JAGUAR)/lib -lpthread  -lunic -ljtml_r -ljinsck_r \
    -ljcc -lnsl -ljlog -o arith arith.cpp
    

    AIX

    This shell script uses the IBM native compiler:

    #!/bin/sh
    . $JAGUAR/bin/setenv.sh
    xlC_r  -g -c -DDEBUG -DJAG_NO_NAMESPACE -DAIX -D_AIX -qcpluscmt -qnoro \
      -qmaxmem=-1 -qarch=com -qtbtable=full  -I $(JAGUAR_JDK13)/include \
      -I $(JAGUAR_JDK12)/include -I. -I$JAGUAR/include  \
      -brtl -L$JAGUAR/lib -ljcc.so -lunic -ljtml_r.so -ljinsck_r.so \
      -lpthread -lnsl -ljutils -o arith arith.cpp
    

    Linux

    This shell script uses the g++ compiler:

    #!/bin/sh
    . $JAGUAR/bin/setenv.sh
    g++ -c -D_GNU_SOURCE=1 -DLINUX -D_LINUX -D_REENTRANT -fPIC \
      -fwritable-strings -pipe -g -DDEBUG -I $(JAGUAR_JDK13)/include \
      -I $(JAGUAR_JDK13)/include/linux -I $(JAGUAR_JDK12)/include \
      -I $(JAGUAR_JDK12)/include/linux  -I. -I$JAGUAR/include \
      -L$JAGUAR/lib -lpthread -ljcc -lnsl -ljtml_r -ljinsck_r \
      -l unic -ljutils -o arith arith.cpp
    

Run the client executable

If you have not refreshed or restarted the server since creating the CPPArithmetic component, do so now before running the client program. Make sure your environment is configured as described in “Verify your environment”.

Run the executable, specifying the server host name and IIOP port number on the command line as follows:

arith iiop://host:iiop-port

For example:

arith iiop://myhost:9000

If everything is working, arith prints the results from the invocation of the multiply method. If not, check the error text printed on the console where you ran the client, and check for error messages in the server log file.





Copyright © 2005. Sybase Inc. All rights reserved. Chapter 4: Creating Enterprise JavaBeans Components and Clients