[Enterprise Extensions only]

Creating your own C++ valuetypes

To aid application development, WebSphere Application Server provides a valuetype library that contains C++ valuetype implementations for some commonly used Java classes in the java.lang, java.io, java.util, and javax.ejb packages. For example, Integer, Float, Vector, Exception, and so on. However, you may want to create your own C++ valuetypes.

The steps below describe how to create a C++ valuetype from an existing sample class called vttest.Book. The term "samples directory" refers to the following directory on your system (assuming that you chose to install samples during your Enterprise services installation):

WAS_HOME/Enterprise/samples/interop/ejb/java/ws4.0/cpp/visibroker4.0/client

  1. If you have private variables in your class that are accessed using JavaBeans getter and setter methods, rename the methods to not use "get" and "set" in their names; for example, rename getProperty() and setProperty() to readProperty() and writeProperty(). This change is necessary to work around a problem with rmic.
  2. Generate the IDL file of your Java class using the following command:
    rmic -idl vttest.Book
  3. Generate the Book.hh and Book_C.cpp files, using the following command:
    idlc -mcpponly -mnohhguards -mdllname=vtlib_name -shh:uc  -Iinclude-path vttest/Book.idl

    This outputs the client-side definition and client bindings files, Book.hh and Book_C.cpp. These two files are generated files and should not be edited.

  4. Generate the Book.ih and Book_I.cpp files, using the following command
    idlc -mcpponly -mnohhguards -mdllname=vtlib_name -eih:ic  -Iinclude-path vttest/Book.idl

    This outputs the skeleton implementation files, Book.ih and Book_I.cpp.

  5. In the generated Book.ih file, add an inheritance from OBV_<package>::<class> to the <module>_<class>_Impl definition.
    For example:
    class vttest_Book_Impl : virtual public ::vttest::Book, virtual
    public ::CORBA:: DefaultValueRefCountBase
    becomes:
    class vttest_Book_Impl : virtual public ::vttest::Book, virtual
    public OBV_vttest::Book, virtual public
    ::CORBA::DefaultValueRefCountBase

    You need this additional inheritance in order to use the default implementation class, OBV_<module>::<class>. See Step 7 for further details. (Note that the generated file <class>_C.cpp contains the syntax required for the class OBV_<module>::<class>.)

  6. Add a class factory definition of the form <module>_<class>_factory to the <class>.ih file.
    For example:
    class <module>_<class>_factory : public ::<module>::<class>_init
    {
      public:
    
         virtual :
            ::CORBA::ValueBase*     create_for_unmarshal();
            ::<module>::<class>*    create();
            ::CORBA::ValueBase*     asValueBase(void* v);
    };
    For Book class, this becomes:
    class vttest_Book_factory : public ::vttest::Book_init
    {
       public:
    
         virtual:
            ::CORBA::ValueBase*      create_for_unmarshal();
            ::vttest::Book*          create();
            ::CORBA::ValueBase*      asValueBase(void* v);
    };

    A template can be found in the factory classes defined in the file Vtlib_i_vb.cxx in your samples directory. The following steps use java_lang_Boolean_factory as a template. Note that this template includes implementation code, which is omitted here. The template also lacks the asValueBase definition, which has been added here:

    class java_lang_Boolean_factory : public java::lang::Boolean_init
    {
    public:
    virtual ::CORBA::ValueBase*
      create_for_unmarshal();
    virtual java::lang::Boolean*
      create__CORBA_WStringValue(::CORBA::WStringValue* arg0);
    virtual java::lang::Boolean*
      create__boolean(::CORBA::Boolean arg0);
    virtual ::CORBA::ValueBase*
      asValueBase(void* v);
    };
    The <class>_init class defined in the generated <class>.hh file shows the create constructors that must be included in the <class>_factory for your class. (The create consructors above are specific to the Boolean valuetype class.) The class Book_init in Book.hh contains only one create constructor:
    virtual  Book* create ()=0;
    Therefore, only that create constructor is added to the class definition for vttest_Book_factory:
    virtual ::vttest::Book* create();
  7. The implementations for the factory class methods need to be added to <class>_I.cpp. Sample implementations can be copied from the file vtlib_i_vb.cxx in the samples directory, such as the following for Boolean_factory:
    virtual CORBA::ValueBase *create_for_unmarshal()
    {
     return new java_lang_Boolean_Impl();
    }
     virtual  java::lang::Boolean* create__boolean (CORBA::Boolean arg0)
    {
     java_lang_Boolean_Impl *ptr = new java_lang_Boolean_Impl();
     ptr->value(arg0);
     return ptr;
    }
    The create_for_unmarshal() method creates a new<class>_Impl object and returns it. The create methods create new <class>_Impl classes and initialize them with appropriate values. (Your create methods must match those in your class.) Since the methods in the implementation file are not virtual, the virtual keyword must be deleted. In their completed form, the implementations for the Book class look like this:
    ::CORBA::ValueBase* vttest_Book_factory::create_for_unmarshal()
    {
     return new ::vttest_Book_Impl();
    }
     ::vttest::Book* vttest_Book_factory::create()
    {
     return new ::vttest_Book_Impl();
    }

    Note that the instance variables of a Java class are mapped into C++ counterparts in the OBV_* namespace's default implementation. (In step 5 you added an inheritance of OBV_<module>::<class>). You need to use these OBV_ getters and setters in your implementation class.

  8. An implementation of the factory method asValueBase() is also required. The method is simply a cast from (void *) to (::CORBA::ValueBase *). It takes the following form:
    ::CORBA::ValueBase* <module>_<class>_factory::asValueBase(void* v)
    {
     return (::CORBA::ValueBase*)((::<module>::<class>*) v );
    }
    You must change the class name to match your own class. In the case of the Book class:
    ::CORBA::ValueBase* vttest_Book_factory::asValueBase(void* v)
    {
     return (::CORBA::ValueBase*)((::vttest::Book*)v);
    }
  9. You need an additional class, <module>_<class>_factoryInit, to register your factory with the ORB. For the Book class, the following class and object instantiation do this:
    class vttest_Book_factoryInit
    {
     public :
    
     vttest_Book_factoryInit()
     {
        ::CORBA::ORB_ptr _vtlibOrb;
        int _argc = 0;
        ::CORBA::ValueFactoryBase_var retfact;
        ::CORBA::ValueFactoryBase_var fact;
        
        // Get access to the ORB.
        _vtlibOrb = ::CORBA::ORB_init(_argc, NULL, "DSOM");
        
        // Create a Book factory.
        fact = new ::vttest_Book_factory();
        
        // Register the factory.
        retfact = _vtlibOrb->register_value_factory((char *)::vttest::Book::Book_RID,
        fact.in() );
     }
    };
    
    // Static instantiation of the class.
    static vttest_Book_factoryInit __vttest_Book_factoryInit;
  10. Code that creates a Book object must be added. You can put this code in the client source. First, an include of .hh must be inserted. For Book, that would be: #include <Book.hh>. Next, a function that creates a Book object must be added.
    For example:
    ::<module>::<class>* create<class>()
    {
     static ::<module>::<class>_init *factory = NULL;
     if ( factory == NULL )
     factory = (<module>::<class>_init*) ::com::ibm::ws::VtlUtil::getFactory(::<module>::<class>::<class>_RID);
     ::<module>::<class>* myPtr = factory->create();
     return myPtr;
    }
    For the Book class, this is:
    ::vttest::Book* createBook()
    {
     static ::vttest::Book_init *factory = NULL;
     factory = (::vttest::Book_init*) ::com::ibm::ws::VtlUtil::getFactory(::vttest::Book::Book_RID);
     ::vttest::Book* bookPtr = factory->create();
     return bookPtr;
    }

You have now completed creation of your own C++ valuetype. Instances of this class can be created and used locally by your client. Because this class is a valuetype, it can also be serialized and sent to a server, where it can be used and returned to your client as well.