Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Advanced CORBA Programming wit C++ - M. Henning, S. Vinoski.pdf
Скачиваний:
65
Добавлен:
24.05.2014
Размер:
5 Mб
Скачать

IT-SC book: Advanced CORBA® Programming with C++

 

in unsigned long

n,

 

out OfferSeq

offers

void

);

 

destroy();

 

};

 

 

interface OfferIdIterator {

 

unsigned long

max_left() raises(UnknownMaxLeft);

boolean

next_n(

n,

 

in unsigned long

 

out OfferIdSeq

ids

void

);

 

destroy();

 

};

 

 

These iterator interfaces are provided by all traders and permit you to retrieve a large result set incrementally. The OfferIterator interface is for use with service offers, whereas OfferIdIterator retrieves the internal identifiers a trader uses to identify its service offers. We show how to use these iterators in Section 19.11.3 and

Section 19.13.2.

19.6.4 Common Types

The CosTrading module defines a number of common types and exceptions that are used by the main interfaces. Instead of presenting all of these type definitions together, we show them as we discuss the various operations. For the remainder of this chapter, whenever we show IDL definitions, they are nested inside the CosTrading module unless we indicate otherwise.

19.7 Exporting Service Offers

We first present the IDL definitions relevant to exporting service offers and then show a C++ code example.

19.7.1 IDL Definitions for the export Operation

The Register interface contains an export operation that creates a new service offer. Here is the IDL definition of export together with the definitions of the types and exceptions it depends on.

// In module CosTrading...

 

typedef string

Istring;

typedef Istring

ServiceTypeName;

typedef Istring

PropertyName;

typedef sequence<PropertyName>

PropertyNameSeq;

typedef any

PropertyValue;

740

IT-SC book: Advanced CORBA® Programming with C++

struct Property {

name;

 

PropertyName

 

PropertyValue

value;

 

};

 

PropertySeq;

typedef sequence<Property>

typedef string

 

OfferId;

exception UnknownServiceType {

 

ServiceTypeName type;

 

};

 

 

exception IllegalServiceType {

 

ServiceTypeName type;

 

};

 

 

exception IllegalPropertyName {

 

PropertyName name;

 

};

 

 

exception DuplicatePropertyName {

 

PropertyName name;

 

};

 

 

exception PropertyTypeMismatch {

 

ServiceTypeName type;

 

Property

prop;

 

};

 

 

exception MissingMandatoryProperty { ServiceTypeName type; PropertyName name;

};

exception ReadonlyDynamicProperty { ServiceTypeName type; PropertyName name;

};

interface Register : TraderComponents, SupportAttributes { exception InvalidObjectRef {

Object ref;

};

exception UnknownPropertyName { PropertyName name;

};

exception InterfaceTypeMismatch { ServiceTypeName type;

Object reference;

};

exception MandatoryProperty { ServiceTypeName type; PropertyName name;

};

741

IT-SC book: Advanced CORBA® Programming with C++

// ...

 

 

OfferId

export(

reference,

 

in Object

 

in ServiceTypeName

type,

 

in PropertySeq

properties

) raises(

InvalidObjectRef, IllegalServiceType, UnknownServiceType, InterfaceTypeMismatch, IllegalPropertyName, PropertyTypeMismatch, ReadonlyDynamicProperty, MissingMandatoryProperty, DuplicatePropertyName

);

// ...

};

This IDL is complex because of the large number of exceptions that export can raise. However, the export operation requires only three parameters.

reference

This parameter is the IOR to the object that provides the service. For example, if you want to create a service offer for a controller, the IOR to the controller is passed in the reference parameter.

type

This is the name of the service type for controllers, such as CCS::Controllers.

properties

The properties parameter supplies the actual values of the properties for the service offer. This parameter is of type PropertySeq, which is a sequence of name-value pairs of type Property:

typedef string

 

Istring;

typedef Istring

 

PropertyName;

typedef any

 

PropertyValue;

struct Property {

name;

 

PropertyName

 

PropertyValue

value;

 

};

 

PropertySeq;

typedef sequence<Property>

For each property defined in the service type, the properties parameter specifies the name of the property and its value as an any.

The export operation ensures that the service offer is in agreement with its service type. The operation can raise the following exceptions:

742

IT-SC book: Advanced CORBA® Programming with C++

InvalidObjectRef

The object reference passed in the reference parameter is invalid. Most traders raise this exception if you pass a nil reference because it does not make sense to advertise a service offer without an actual service object. A trader can also raise this exception if the reference denotes a non-existent object. However, most traders do not implement this check because of the additional run-time cost it incurs.

IllegalServiceType

The service type name passed in the type parameter is syntactically invalid.

UnknownServiceType

The service type name passed in the type parameter denotes a non-existent service type.

InterfaceTypeMismatch

The object reference passed in the reference parameter has a type that is not the same as, nor derived from, the IDL interface type specified in the service type. This exception exists so that you cannot place a reference to the wrong kind of object into a service offer (see page 845). Note that many traders never raise this exception. Such traders make you responsible for ensuring that the IDL interface type of the service provider matches the service type.

IllegalPropertyName

The name of a property is not a simple IDL identifier.

PropertyTypeMismatch

The value of a property has a type that differs from the type for the property as specified in the service type. You will get this exception if, for example, the any value of a property contains a string but the service requires the property to contain a Boolean value.

ReadonlyDynamicProperty

Read-only properties cannot be dynamic, so this exception is raised if you supply a dynamic property value for a read-only property.

MissingMandatoryProperty

The properties parameter does not contain a value for a property that is mandatory.

DuplicatePropertyName

The properties parameter contains more than one definition for a particular property.

The return value from export is of type OfferId, which is a string. The offer ID is an opaque value assigned by the trader; it uniquely identifies the new service offer. You must take care to store the return value somewhere, at least if you want to be able to withdraw the service offer. This is necessary because the withdraw operation requires you to supply the offer ID returned by the export operation. If you lose the offer ID, it is possible to locate the offer and to withdraw it, but only with considerable effort (see Sections 19.12 and 19.14), so it is best not to lose the offer ID in the first place.

743

IT-SC book: Advanced CORBA® Programming with C++

19.7.2 C++ Code for Exporting Service Offers

To export (create) a new service offer, you must hold an object reference to the trader's Register interface. You obtain that reference by reading the register_if attribute on the Lookup interface returned from resolve_initial_references. After you have a reference to the Register interface, you can invoke the export operation. The following code example shows how to create a service offer for a controller. We assume that we have previously created a service type for controllers as shown on page 851.

using namespace CosTrading;

//Get reference to Lookup interface. Lookup_var lookup;

lookup = resolve_init<CosTrading::Lookup>(orb, "TradingService");

//Navigate to Register interface.

register_var regis = lookup->register_if(); if (CORBA::is_nil(regis)) {

cout < "Trader does not support updates." < endl; throw 0;

}

// Fill in property definition for controller. PropertySeq props;

props.length(3);

props[0].name = CORBA::string_dup("Model"); props[0].value <= "BFG-9000";

props[1].name = CORBA::string_dup("Phone"); props[1].value <= "123 456-7890";

props[2].name = CORBA::string_dup("Description"); props[2].value <= "Deluxe model for advanced users.";

//Get the reference to the controller we want to advertise. CCS::Controller_var ctrl = ...;

//Export the offer.

OfferId_var offer_id = regis->_cxx_export(

ctrl, "CCS::Controllers", props );

cout < "Created new offer with id " < offer_id < endl;

Note that this code supplies only the mandatory properties and does not supply values for optional properties. We could also have supplied values for the optional properties, in which case their type would have to match the service type definition.

19.7.3 Additional Properties

If you take a careful look at the preceding code example, you will notice something unusual. The code creates a property named Description for the export operation

744

IT-SC book: Advanced CORBA® Programming with C++

even though the service type for controllers does not define this property. This behavior is perfectly OK and does not cause any problems. The trader specification requires the trader to accept properties that are not mentioned by the service type. In other words, the trader enforces the type system only for those properties that are actually defined by the service type but accepts any property with any type of value if that property is not defined by the service type.

The main motivation for this behavior is extensibility. For example, if we are in the business of selling controllers, we may be forced to use an industry-standard service type to advertise the controllers. However, that makes it difficult to distinguish ourselves from the competition. For example, we may want to have properties that describe unique features of our controller that were not anticipated when the service type was agreed on.

Although additional properties that do not appear in the service type can be useful, they are also something of a two-edged sword. Unless we are careful, the following may happen:

using namespace CosTrading;

 

// Get reference to register interface...

 

Register_var regis = ...;

 

// Fill in property definition for controller.

 

PropertySeq props;

 

props.length(3);

 

props[0].name = CORBA::string_dup("Model");

 

props[0].value <= "BFG-9000";

 

props[1].name = CORBA::string_dup("Phone");

 

props[1].value <= "123 456-7890";

 

props[2].name = CORBA::string_dup("MasDevices");

// Oops!

props[2].value <= (CORBA::ULong)256;

 

//Get the reference to the controller we want to advertise. CCS::Controller_var ctrl = ...;

//Export the offer.

OfferId_var offer_id = regis->_cxx_export(

ctrl, "CCS::Controllers", props );

cout < "Created new offer with id " < offer_id < endl;

You must look closely to spot the problem with this code. The code initializes the third element of the props sequence to indicate the maximum number of devices supported by the controller. However, the code contains a typo: instead of setting the value of the MaxDevices property, the code creates an additional property called MasDevices. Unfortunately, this error goes undetected because MaxDevices is an optional property. As far as the service type is concerned, there is nothing wrong with this service offer.

745