• No results found

BadComponentReference exception can be raised if the input reference is not local (NON_LOCAL_REFERENCE), not a component reference

4.5 The Client Programming Model

4.5.1 Component-aware Clients

Clients that are defined using the IDL extensions in the Component Model chapter are referred to as component-aware clients. Such clients can avail themselves of the unique features of CORBA components that are not supported by ordinary CORBA objects. The interaction between these clients and a CORBA component are outlined in the following sections. A component-aware client interacts with a component through one or more CORBA interfaces:

¥

The equivalent interface implied by the component IDL declaration.

¥

Zero or more supported interfaces declared on the component specification.

¥

Zero or more interfaces defined by the provides clauses in the component definition.

¥

The home interface that supports factory and finder operations. Furthermore a component-aware client locates those interfaces using the Components::HomeFinder ora naming service. The starting point for client interactions with the component is the resolve_initial_references operation on CORBA::ORB that provides the initial set of object references.

4.5.1.1 Initial References

Initial references for all services used by a component client are obtained using the CORBA::ORB::resolve_initial_references operation. This operation currently supports the following references required by a component client:

¥

Transaction Current (ÒTransactionCurrentÓ)

¥

Security Current (ÒSecurityCurrentÓ)

¥

Notification Service (ÒNotificationServiceÓ)

¥

Interface Repository (ÒInterfaceRepositoryÓ) for DII clients

¥

Home Finder (ÒComponentHomeFinderÓ)

The client uses ComponentHomeFinder (defined in Section 1.8, ÒHome Finders,Ó on page 1-42) to obtain a reference to the HomeFinder interface.

4.5.1.2 Factory Design Pattern

For factory operations, the client invokes a create operation on the home. Default create operations are defined for each category of CORBA components for which code can be automatically generated. These operations return an object of type

CORBA::Component that must be narrowed to the specific type. Alternatively, the component designer may specify custom factories as part of the component definition to define a type-specific signature for the create operation. Because these operations are defined in IDL, operation names can be chosen by the component designer. All that is required is that the operations return an object of the appropriate type.

A client using the factory design pattern uses the HomeFinder to locate the

component factory (CCMHome) by interface type. The HomeFinder returns a type- specific factory reference, which can then be used to create new instances of the component interface. Once created, the client makes operation requests on the reference representing the interface. This is illustrated by the following code fragment: // Resolve HomeFinder org.omg.CORBA.Object objref = orb.resolve_initial_references(“ComponentHomeFinder”); ComponentHomeFinder ff = ComponentHomeFinderHelper.narrow(objref); org.omg.CORBA.Object of = ff.find_home_by_type(AHomeHelper.id()); AHome F = AHomeHelper.narrow (of);

org.omg.Components.ComponentBase AInst = F.create(); A Areal = AHelper.narrow (AInst);

// Invoke Application Operation answer = A.foo(input);

4.5.1.3 Finder Design Pattern

A component-aware client wishing to use an existing component instance (rather than create a new instance) uses a finder operation. Finders are supported for entity components only. ClientÕs may use the HomeFinder as described in Section 1.8, ÒHome Finders,Ó on page 1-42 to locate the componentÕs home or they may use CORBA naming to look up a specific instance of the home by symbolic name. A client using the finder design pattern uses the CosNaming::NamingContext interface to look up a symbolic name. The naming service returns an object reference of the type previously bound. The client then makes operation requests on the reference representing the interface. This is illustrated by the following code fragment: org.omg.CORBA.Object objref =

orb.resolve_initial_references(“NamingService”);

NamingContext ncRef = NamingContextHelper.narrow(objref); // Resolve the Object Reference in Naming

NameComponent nc = new NameComponent(“A“,””); NameComponent path[] = {nc};

A aRef = AHelper.narrow(ncref.resolve(path)); // Invoke Application Operation

answer = A.foo(input);

4.5.1.4 Transactions

A component-aware client may optionally define the boundaries of the transaction to be used with CORBA components. If so, it uses the CORBA transaction service to ensure that the active transaction is associated with subsequent operations on the CORBA component.

The client obtains a reference to CosTransactions::Current by using the

CORBA::ORB::resolve_initial_references operation specifying an ObjectID of ÒTransactionCurrentÓ. This permits the client to define the boundaries of the transaction; that is, how many operations will be invoked within the scope of the clientÕs transaction. All operations defined for Current may be used as defined by the CORBA Transaction service with the following exceptions:

¥

The Control object returned by get_control and suspend may only be used with resume.

¥

Operations on Control may raise the NO_IMPLEMENT exception with CORBA components.

The Control interface in the CORBA transaction service supports acces- sors to the Coordinator and Terminator interfaces. The Coordinator is used to build object versions of XA resource managers. The Terminator is used to allow a transaction to be ended by someone other than the origina- tor. Since neither function is within the scope of the demarcation subset of CORBA transactions used with CORBA components, we allow CORBA

transaction services implementations used with CORBA components to raise the NO_IMPLEMENT exception.

The following code fragment shows a typical usage: org.omg.CORBA.Object objref =

orb.resolve_initial_references(“TransactionCurrent”); Current txRef = CurrentHelper.narrow(objRef);

txRef.begin();

// Invoke Application Operation answer = A.foo(input);

txRef.commit();

4.5.1.5 Security

A component-aware client uses the existing CORBA security mechanism to manage security for a CORBA component. There are two scenarios possible:

¥

Use of SSL for establishing client credentials

CORBA security today does not define a standard API for clients to use with SSL to set the credentials that will be used to authorize subsequent requests. The credentials must be set in a way that is proprietary to the client ORB.

¥

Use of SECIOP by the client ORB.

In this case, CORBA security does define an API and it must be used by the client to establish the credentials to be used to authorize subsequent requests.

Security processing for CORBA components uses a subset of CORBA security. For SECIOP, the client sets the credentials to be used with subsequent operations on the component by using operations on the SecurityLevel2::PrincipalAuthenticator. The client obtains a reference to SecurityLevel2::Current by using the

CORBA::ORB::resolve_initial_references operation specifying an ObjectID of ÒSecurityCurrentÓ. This permits the client to access the PrincipalAuthenticator interface to associate security credentials with subsequent operations. The following code fragment shows a typical usage:

org.omg.CORBA.Object objref = orb.resolve_initial_references(“SecurityCurrent”); org.omg.SecurityLevel2.PrincipalAuthenticator secRef = org.omg.SecurityLevel2.PrincipalAuthenticatorHelper.narrow (objRef); secRef.authenticate(...);

// Invoke Application Operation answer = A.foo(input);

4.5.1.6 Events

Component-aware clients wishing to emit or consume events use the component APIs defined in the Component Model chapter. Alternatively, they may use CORBA notification directly and conform to the subset supported by CORBA components (see Section 4.5.2.6, ÒEvents,Ó on page 4-51 for details).