Chapter 16 Creating CORBA C++ Components
After you generate the method skeleton file, class header file, and class implementation template, write the code for each method in the class implementation template (you can also write your class implementation from scratch and replace the generated class implementation template).
You must use scoped names to specify the CORBA IDL module, the Jaguar SessionManager IDL module, and any component IDL modules that you want to execute methods on. To make using scoped names easier, you can use the C++ using statement for the IDL module namespaces as in the following example:
using namespace CORBA;
using namespace SessionManager;
If your C++ compiler does not support namespaces, define a compiler macro JAG_NO_NAMESPACE when compiling your source files.
CORBA::is_nil(Object) can be used to verify that a specific interface is implemented by a component.
As with any C++ class, you use the constructor and destructor to initialize and perform any cleanup of objects.
Constructors of class variables in file scope not called If you declare a class variable in file scope and compile it into a shared object, such as a component, the Solaris C++ compiler doesn't call the constructor of the class variable. If the variables need to be in scope only for a particular function, procedure or module, then declare these variables in the appropriate function, procedure, module; otherwise declare these variables in the class definition.
You can also include Jaguar C routines to:
Coding these C routines is described in "Write methods".
This section describes how to write methods for Jaguar-specific APIs, including C routines, accessing SSL client certificates, and issuing intercomponent calls. A C++ method signature must use the return types and parameter datatypes described in "Supported datatypes". To implement any of the features that require Jaguar C routines, you must include jagpublic.h and implement the methods for each feature as follows:
You can return result sets by:
return NULL;
For more information about these methods, see the Jaguar CTS API Reference.
You can code components (and clients) to initiate and complete transactions using the OTS (Object Transaction Service) CosTransactions::Current or CosTransactions::TransactionFactory interfaces.
In order to use OTS, you must enable the Jaguar server to use the OTS/XA transaction coordinator. See the Jaguar CTS System Administration Guide for more information.
To use the functionality of these interfaces, include CosTransactions.hpp in your source file.
To explicitly use transactions in a component or client, use the CosTransactions::Current interface to perform these tasks.
The TransactionFactory interface is included in Jaguar only to maintain compatibility with the CORBA OTS specification--Sybase recommends that you use the CosTransactions::Current interface to create explicit transactions.
Sybase recommends that you use suspend with caution so as not to conflict with the Jaguar component model. For example, do not use suspend to take control of a transaction that it does not control.
To initialize the ORB and retrieve a reference to the CosTransactions::Current interface, specify the TransactionCurrent ObjectId, which identifies the CosTransactions::Current interface, to the resolve_initial_references method, and narrow it (using the _narrow method) to the CosTransactions::Current interface. Use the is_nil method to verify that the reference to the CosTransactions::Current interface is valid.
The following code fragment shows how to initialize the ORB from a client. ORB_init must take the argumentList array that specifies the ORBNameServiceURL parameter. You can also set the ORBNameServiceURL using the JAG_NAMESERVICEURL environment variable.
int argumentCnt = 1;
char *argumentList[] = {
{ "-ORBNameServiceURL iiop://<hostnamehere>:9000" },
{ "" }
};
try {
CORBA::ORB_var orb = CORBA::ORB_init(argumentCnt, argumentList, 0);
cerr << "Orb init" << endl;
CORBA::Object_var crntObj =
orb->resolve_initial_references
("TransactionCurrent");
CosTransactions::Current_var CurrentIntf =
CosTransactions::Current::_narrow(crntObj);
if( CORBA::is_nil(CurrentIntf) )
{
cerr << "Error getting Current" << endl;
exit(-1);
}
cerr << "Got Current" << endl;
The following code fragment shows how to initialize the ORB from a component. ORB_init does not need to take any parameters.
orb = CORBA::ORB_init(argumentCnt, NULL, 0);
cerr << "Orb init" << endl;
CORBA::Object_var crntObj =
orb->resolve_initial_references
("TransactionCurrent");
CurrentIntf = CosTransactions::Current::_narrow(crntObj);
if( CORBA::is_nil(CurrentIntf) )
{
cerr << "Error getting Current" << endl;
/* could be due to:
** 1. Component not BeanManaged/OTS Style
** 2. Already in a Txn
** 3. not running under OTS
*/
return CS_FAIL;
}
cerr << "Got Current" << endl;
After retrieving a reference to the CosTransactions::Current interface, you can call any of the CosTransactions::Current methods on the CosTransactions::Current reference. After executing the begin method, execute the database operations you want to include in the transaction. Depending on whether the database operations succeed or fail, you can execute other appropriate methods, such as commit, rollback, or rollback_only. This code fragment shows how to begin a transaction and commit or roll it back depending on the return codes received from the databases.
CurrentIntf->begin();
ret = JagCmGetConnection( &cache,
(SQLCHAR *) USERID, (SQLCHAR *) PASSWD,
(SQLCHAR *) xaresource, (SQLCHAR *) "CTLIB_110",
(void*) &conn, JAG_CM_UNUSED );
if (ret != CS_SUCCEED) {
cerr << "Error getting connection" << endl;
CurrentInt->rollback();
}
CurrentIntf->commit(CS_FALSE);
To execute a method outside of a transaction, you can write the code to perform either:
To execute tasks outside of a transaction using the suspend and resume methods:
This code fragment shows how to execute tasks outside of a transaction. The suspend method returns the control context. You specify the control context when you use the resume method to restart the transaction. Catch the InvalidControl exception, which may be raised when a control context is out of scope (and not null).
sus_ctrl = CurrentIntf->suspend();
/* The following method is not in the transaction */
component1->method2();
CurrentIntf->resume(sus_ctrl);
/* The following methods are invoked
in the transaction */
component2->method1();
CurrentIntf->commit(CS_FALSE);
}
catch(CosTransactions::SubtransactionsUnavailable
&ex )
{
cerr << "Exception: SubTxnUnavailable " << ex._jagExceptionCode << endl;
}
catch(CosTransactions::NoTransaction &ex )
{
cerr << "Exception: NoTransaction " << ex._jagExceptionCode << endl;
}
catch(CosTransactions::InvalidControl &ex )
{
cerr << "Exception: InvalidCtrol " << ex._jagExceptionCode << endl;
}
catch(...)
{
cerr << "Caught Unexpected exception" << endl;
exit(-1);
}
The CosTransactions module includes these exceptions:
A heuristic decision is a decision to commit or roll back updates that one or more participants in a transaction make without waiting for the consensus decision from the transaction coordinator. These types of commits and rollbacks are also called heuristic commits and heuristic rollbacks. When a heuristic commit or rollback is made, the transaction can become inconsistent. Therefore, a heuristic commit or rollback is made only in unusual circumstances such as communication failures. When the System Administrator issues a heuristic commit or rollback from Jaguar Manager, a heuristic exception is raised.
Clients can connect to a secure IIOP port using an SSL client certificate. You can issue intercomponent calls to the built-in CtsSecurity/SessionInfo component to retrieve the client certificate data, including:
This component implements the CtsSecurity::SessionInfo IDL interface. HTML documentation is available for the interface in the html/ir subdirectory of your Jaguar installation. You can view it by loading the main Jaguar HTML page, then clicking the "Interface Repository" link.
The CtsSecurity::UserCredentials interface is deprecated The CtsSecurity::UserCredentials interface, which is implemented by the CtsSecurity/UserCredentials component, has been replaced by the CtsSecurity::SessionInfo interface, which provides additional functionality such as certificate parsing. Jaguar supports the CtsSecurity::UserCredentials interface for backwards compatibility. Please use the interface CtsSecurity::SessionInfo if developing new components.
To invoke other components, instantiate a stub for the second component, then use the stub to invoke methods on the component.
You must use a stub to issue intercomponent calls. If you call methods in another C++ component directly, Jaguar features such as transactions and security will not work.
To invoke methods in other components, create an ORB instance to obtain object references to other components and invoke methods on the object references. You obtain object references for other components on the same server by invoking string_to_object with the IOR string specified as Package/Component. For example:
CORBA::Object_var obj =
orb->string_to_object("MyPackage/MyComponent");
MyModule::MyInterface_var i =
MyModule::MyInterface::_narrow(obj);
When making intercomponent calls using string_to_object, the user name of the client that executed the component is automatically used for authorization checking.
To instantiate components hosted by another Jaguar server, you must use the techniques described in Chapter 17, "Creating CORBA C++ Clients"
C++ components (and PowerBuilder NVOs) can make intercomponent calls across different servers using SSL in much the same way as any other C++ client. However, be aware of these considerations:
com.sybase.jaguar.component.mysslqop=sybpks_intl
Your component may need to invoke methods on a component hosted by another vendor's CORBA server-side ORB. Sybase recommends that C++ components use the Jaguar client-side ORB for all IIOP connections made from Jaguar components. See "Connecting to third-party ORBs using the Jaguar client ORB" for more information.
Copyright © 2000 Sybase, Inc. All rights reserved. |