Distributed Systems Session 6: Implementing Distributed Systems with OMG/CORBA Christos Kloukinas Dept. of Computing City University London © City University London, Dept. of Computing Distributed Systems / 6 - 1 Announcements Milestone 2 Due today » Server Implementation » A least version 1 » 1 submission per pair » Identify your partner in the submission Some Self Assessment questions up on CitySpace © City University London, Dept. of Computing Distributed Systems / 6 - 2 Taking Stock: Module Outline 1 Motivation 2 Distributed Software Engineering 3 Communication 4 RMI 5 CORBA vs RMI 6 Building Distributed Systems with CORBA - Common Problems in Distributed Systems 7 Naming and Trading 8 Concurrent Processes and Threads 9 Transactions 10 Security © City University London, Dept. of Computing Distributed Systems / 6 - 3 0.0 CORBA IDL CORBA IDL is very expressive and widely available on many platforms for different programming languages. This has motivated the use of CORBA as a mechanism to explain, study and experiment with principles of distributed systems © City University London, Dept. of Computing Distributed Systems / 6 - 4 0.1 Last session: Object Management Architecture Application Objects CORBA facilities Object Request Broker Transactions Naming trading concurrency © City University London, Dept. of Computing Security Lifecycle CORBA services Distributed Systems / 6 - 5 0.2 Last session: CORBA Architecture © City University London, Dept. of Computing Distributed Systems / 6 - 6 0.3 Last session Summary Revisited CORBA/IDL Static Vs Dynamic Invocation Interface Repository Dynamic Invocation Interface (DII) Dynamic Skeleton Interface (DSI). Basic Object Adapter CORBA Communication and the IIOP Protocol Hello World Example Compare and Contrast, CORBA and JAVA RMI © City University London, Dept. of Computing Distributed Systems / 6 - 7 Outline of Session 6 IDL programming language bindings. Difference between centralised and distributed object lifecycle. CORBA Lifecycle Service. © City University London, Dept. of Computing Distributed Systems / 6 - 8 Outline To actually develop distributed systems an IDL is not sufficient. The operations declared at the interface need to be implemented in order to be used. For both implementation and use of distributed operations, bindings to existing programming languages need to be defined. The standardisation of these programming language bindings will then facilitate the interoperability between distributed objects that are implemented in different programming languages to form so called polylingual applications. A further prerequisite for distributed object-oriented applications is the ability to create distributed objects in a location transparent way. Moreover, objects may have to be copied or relocated and during that may have to be migrated to different platforms. Also objects may have to be removed. © City University London, Dept. of Computing Distributed Systems / 6 - 9 1 IDL Programming Language Bindings 1 Polylingual applications 2 Standardisation of bindings 3 Available bindings 4 What bindings need to address 5 An example: IDL/Java © City University London, Dept. of Computing Distributed Systems / 6 - 10 1.1 Polylingual Applications Distributed computing frameworks, such as CORBA are not only used for the construction and a-priori integration of new components. They are probably more often used for the a-posteriori integration of applications from existing components. Polylingual applications have components in different programming languages. To achieve interoperability between these components, language bindings are needed that map different language concepts onto each other. Problem: with n different languages, n(n-1) different language bindings needed. Solution: One language (such as IDL) as a mediator. Requires only n bindings. © City University London, Dept. of Computing Distributed Systems / 6 - 11 1.1 Polylingual Applications with IDL Client side •Multiple polylingual clients accessing same object Java Client IDL Infrastructure •IDL/JAVA binding enables client to invoke exported operations on server object © City University London, Dept. of Computing Object Implementation Side IDL C++ Obj. Impl. •IDL/C++ Binding used to implement exported operations Distributed Systems / 6 - 12 1.2 Standardisation of Bindings Facilitate portability: » If different ORB vendors used different programming language bindings, neither object implementations nor clients of these implementations would be portable. As this is very undesirable, the OMG has standardised a number of language bindings. » ORB vendors must respect these language bindings to be able to claim that they are CORBA compliant. Decrease learning curve of developers: » Developers who studied one language binding do not have to learn the binding again if they switch to an ORB from another vendor. © City University London, Dept. of Computing Distributed Systems / 6 - 13 1.3 Available Bindings C C++ Smalltalk Ada-95 OO Cobol Java © City University London, Dept. of Computing It is sufficient for the compliance of an object request broker product to the CORBA standard if it provides one of these bindings. Most brokers, however, provide more than one binding. Nevertheless, no product is currently available that implements all bindings. Distributed Systems / 6 - 14 1.4 What Bindings Need to Address Atomic data types and type constructors Constants Interfaces and multiple inheritance Object references Attribute accesses Operation execution requests Exceptions Invocation of ORB operations © City University London, Dept. of Computing Distributed Systems / 6 - 15 1.5 An Example: IDL/Java 1 Modules 2 Atomic Types 3 Enumerations 4 Records 5 Interfaces 6 Attributes 7 Operations 8 Inheritance 9 Exceptions 10 Operation Execution Requests © City University London, Dept. of Computing Distributed Systems / 6 - 16 1.5.1 Modules As an example, assume that an interface Account is included in the IDL BankApplication module. This interface will be represented in Java as class Account. From outside the package BankApplication, the class can be accessed using BankApplication.Account. Note that in this way the avoidance of name clashes is supported, which makes the approach particularly useful for the construction of large distributed systems. © City University London, Dept. of Computing Distributed Systems / 6 - 17 1.5.1 Modules IDL: Java: module BankApplication { ... }; package BankApplication; ... © City University London, Dept. of Computing Distributed Systems / 6 - 18 1.5.2 Atomic Types IDL Java short/unsigned short long/unsigned long long long/unsigned long long float double char boolean octet string short int long float double char boolean byte String © City University London, Dept. of Computing Distributed Systems / 6 - 19 1.5.2 Atomic Types (ctd.) Most atomic types map naturally to Java Java’s platform independence is of great value here. In the IDL to C++ mapping, for example, there is the problem of different representations on different platforms (shorts can be 32 or 64 bit on Unix and 16 bit on PCs or the significance of a byte may be different (low endian vs high endian architecture). Therefore IDL-to-C++ does not map anything to atomic C++ types. Java does not have this problem because the Java Virtual Machine is standardised. © City University London, Dept. of Computing Distributed Systems / 6 - 20 1.5.3 Enumerations IDL provides an enumeration type; » An ordered list of identifiers whose values are assigned in ascending order according to their order in enumeration module addresses{ enum Sex {male, female}; }; Java has no enumeration type and therefore has to implement an enumeration as a class! The class provides constants of the enumeration type which is internally realised as integers Additionally the Java class provides a method to convert integers to the enumeration type © City University London, Dept. of Computing Distributed Systems / 6 - 21 Enumeration (2) One shortcoming of Java is the missing enumeration type. An IDL enumeration is mapped to an enumeration class in Java Example: The above IDL enumeration in implemented by the Java code below. The constants can be accessed as Sex.male and Sex.female . Integers (0 and 1 in this case) can be translated to enumeration type package Addresses; public final class Sex implements java.lang.Cloneable { public static final int _male = 0; public static final Sex male = new Sex(_male); public static final int _female = 1; public static final Sex female = new Sex(_female); public static final Sex IT_ENUM_MAX = new Sex(Integer.MAX_VALUE); public int value () {return ___value;} public static Sex from_int (int value) { switch (value) { case _male : return male; case _female : return female; default : throw new org.omg.CORBA.BAD_PARAM("Enum out of range"); } } private Sex (int value) { ___value = value;} private int ___value; public java.lang.Object clone(){return from_int(___value);} } © City University London, Dept. of Computing Distributed Systems / 6 - 22 1.5.4 Records IDL Java struct Info { long height; short weight; }; final public class Info { public int height; public short weight; public Info() {} public Info(int height, short weight){ this.height = height; this.weight = weight;} }; Likewise, IDL records are mapped to a Java class. Attributes of the record are mapped to public attributes of the class. Names used in IDL are used directly in Java. © City University London, Dept. of Computing Distributed Systems / 6 - 23 1.5.5 Interfaces IDL interfaces are translated into Java public interfaces. The reasons for that are obvious: The inheritance and subtype relationships in IDL can be mapped to inheritance in Java and interface components, such as attributes and operations can be implemented as Java methods. The interface name can be kept as the class name because no name conflicts can occur in Java which would not have already been detected in IDL. © City University London, Dept. of Computing Distributed Systems / 6 - 24 1.5.6 Attributes IDL interface person { attribute readonly string name; attribute address lives_at; }; Java public interface person { public String name(); public address lives_at(); public void lives_at(address value); }; © City University London, Dept. of Computing Distributed Systems / 6 - 25 1.5.6 Attributes (ctd.) IDL attributes are implemented as Java class attribute with access methods. For readonly attributes a single (get) method is generated and for other attributes a pair of (set and get) methods is created. An access of an attribute from a remote object can fail for similar reasons as an operation execution request. These failures are handled using exceptions in both Java and IDL. The visibility of methods that implement attributes is public. This is necessary to retain the IDL semantics that any attribute that is declared can be accessed from other classes. © City University London, Dept. of Computing Distributed Systems / 6 - 26 1.5.7 Operations IDL interface Dog { void bark(out short times); void growl(in string at); }; Java public interface Dog{ public void bark(org.omg.CORBA.ShortHolder times); public void growl(String at); }; © City University London, Dept. of Computing Distributed Systems / 6 - 27 1.5.7 Operations (ctd.) Operations defined in an IDL interface are mapped to public Java methods of the class that represents the interface. The method name is retained because again this cannot cause scoping problems in Java that would not have been detected in IDL. Likewise, parameter names are retained as they cannot cause name clashes. The mapping of parameter types is more complicated. Since Java does NOT provide pointers, parameters of atomic type are passed by value, IMPORTANT STUFF Truth #1: Everything in Java is passed by value. Objects, however, are never passed at all.., ONLY their references are (by value again…). Truth #2: The values of variables are always primitives or references, never objects. © City University London, Dept. of Computing Distributed Systems / 6 - 28 Operations ctd. (in, out,inout parameters) IN : to be passed with a meaningful value » Value of the actual parameter is copied into the formal parameter when the operation is invoked. Modification of formal parameter affects only the formal parameter, not the actual parameter. This is the most common form of parameter passing and is the only one provided in C & Java(CALL-BY-VALUE) OUT: Whose value will be changed by operation » The value of the formal parameter is copied into the actual parameter when the procedure returns. Modifications to the formal parameter do not affect the formal parameter until the function returns. (CALL-BY-RESULT) » So it really should be passed by reference (to be modified!) INOUT: Combination of IN and OUT E.G. Consider f(s) and call f(g), s: formal parameter,and g actual parameter © City University London, Dept. of Computing Distributed Systems / 6 - 29 Operations ctd (implementing out, inout) CORBA IDL in parameter implement call-by-value semantics , JAVA supports this, so consequently in maps to normal JAVA parameters and requires no additional effort. whereas IDL’s out and inout parameter do NOT have JAVA counterparts, SO some additional mechanism is required for call-by-result, etc Java creates for every type a holder class, a container, an object which wraps up the value. Since object references can be passed by value the out/inout parameter can now be realised in java programs. I.e Clients instantiate an instance of appropriate Holder class, which is then passed by value. To support portable stubs and skeletons, holder classes also implement the org.omg.CORBA.portable.Streamable interface, to allow for marshalling and unmarshalling. © City University London, Dept. of Computing (The whole object is sent!) Distributed Systems / 6 - 30 Operations (2) •Contents of the instance are modified by server invocation •Client then uses possibly changed contents •The short-holder class of the above example is, for example, part of the org.omg.CORBA package: package org.omg.CORBA; public final class ShortHolder { public short value; public ShortHolder() {} public ShortHolder(short s) { value = s; } } •In language bindings providing pointers out/inout parameters are realised by pointers © City University London, Dept. of Computing Distributed Systems / 6 - 31 1.5.8 Inheritance IDL interface student : person { attribute string subject; }; Java public interface student extends person { string subject(); void subject(String value); } IDL provides multiple inheritance, JAVA does not. How is the problem solved?? © City University London, Dept. of Computing Distributed Systems / 6 - 32 1.5.8 Inheritance (ctd.) Inheritance between IDL interfaces is implemented as inheritance between the respective Java interfaces. Note : Java interfaces do allow multiple inheritance whereas Java classes do not. Therefore IDL interfaces with multiple inheritance map to JAVA interfaces with multiple inheritance When implementing such a Java interface one uses the implementskeyword and therefore inherits only the names of methods and attributes and not any code. The Java class implementing a Java interface with multiple inheritance implements every single method/attribute of the interface and is therefore in control. © City University London, Dept. of Computing Distributed Systems / 6 - 33 1.5.9 Exceptions IDL Java interface employee : person { exception too_young{...}; void retire() raises (too_young); }; public interface Employee extends org.omg.CORBA.Object { public void retire() throws EmployeePackage.too_young; } Exceptions that are declared within an interface are mapped to Java classes. © City University London, Dept. of Computing Distributed Systems / 6 - 34 Exceptions (2) The previous example leads to the following Java class: package Exception.EmployeePackage; public final class too_young extends org.omg.CORBA.UserException implements java.lang.Cloneable { public String explanation; public short age; public too_young() {super();} public too_young(String explanation,short age) { super(); this.explanation = explanation; this.age = age;} ...} Note that programming languages such as C which do not provide exceptions, model exceptions by additional parameters to methods. (much faster but easier to ignore…) © City University London, Dept. of Computing Distributed Systems / 6 - 35 1.5.10 Operation Execution Requests Operation execution requests have no counterpart in IDL as IDL is an interface and not an implementation definition language! © City University London, Dept. of Computing Distributed Systems / 6 - 36 1.5.10 Operation Execution Requests Java employee emp; ... try { emp.retire(); } catch (too_young e){ // Handle the Specific Exception } catch (SystemException se){ switch (SysEx.minor() ) { case BAD_PARAM : ... ; break; case NO_MEMORY : ... ; break; }; }; © City University London, Dept. of Computing Distributed Systems / 6 - 37 2 Lifecycle Service Application Objects CORBA facilities Object Request Broker Lifecycle © City University London, Dept. of Computing CORBA services Distributed Systems / 6 - 38 Introduction/Summary The problem of distributed object life cycle is the problem of » Creating an Object, Deleting an Object, Moving and Copying an object, Operating on a graph of distributed objects. Client model of object lifecycle is based on » Factories and target objects supporting LifeCycleObject interface which defines operation for delete, move and copy GenericFactory interface is defined » Generic factory is sufficient to create objects of different types » By Defining GenericFactory interface, implementations that administer resources are enabled. © City University London, Dept. of Computing Distributed Systems / 6 - 39 2.1 Introduction Component creation in a distributed system is more complicated than in a centralised system mainly because: » 1) Often the component is to be created on a non-local machine. The component creation mechanisms available in programming languages (such as constructors in Java) cannot be used because location specification has to be included. » 2) Location has to be identified, and identification must be transparent More problems arise for duplication and migration of components » due to potentially heterogeneous source and target platform, also 2) above The deletion of components is more difficult as well. » Garbage collection techniques assume that all objects are available in one address space. This is not the case in a distributed system. The techniques cannot be directly applied. © City University London, Dept. of Computing Distributed Systems / 6 - 40 2.1 Introduction (ctd.) creation Client Obj1 duplication migration removal Obj1 © City University London, Dept. of Computing Obj1 Obj1 replication Obj2 Obj1 Server Obj1 Obj1 Obj1 Obj3 Distributed Systems / 6 - 41 2.2 CORBA Lifecycle Service Object Creation Object creation is done in the CORBA lifecycle service by so called Factory objects. These are plain CORBA objects themselves that export an operation that create and return new objects. The factory objects use object constructors for the implementation of these creation operations. The new objects, therefore, run in the same address space as the factory object. An example is the personFactory object which can be used to create a new object of type person. To do so a client who wishes to create a person object calls the operation createPerson which will return a reference to a newly created person object. This person object will run on the same machine as the object of type personFactory. The problem of location transparency then gets down to locating factory objects. © City University London, Dept. of Computing Distributed Systems / 6 - 42 2.2 Object Creation (ctd.) Object Creation is done in CORBA lifecycle service by factory objects The life cycle module exports the FactoryFinder interface, which supports factory location. A client wishing to locate a factory can invoke the find_factories operation, which will return a sequence of Factory objects. The parameter of the find_factory operation is a key that can be considered as an external (and location independent) name. If no factories are found with that name, the NoFactory exception will be raised. Factories register with a factory finder using a private protocol. This protocol is likely to be defined in an interface that inherits from the FactoryFinder interface.This, however, is transparent for clients. Factory finders are not only used for the immediate location of a factory (for creation purposes), but they are also used as proxies (placeholders) for location information that is to be passed to move and copy operations. © City University London, Dept. of Computing Distributed Systems / 6 - 43 2.2 Object Creation Factory location supported by: interface FactoryFinder { Factories find_factories (in Key factory_key) raises (NoFactory); }; Factory finder objects can be located by other means (e.g. naming or trading).(will discuss in next lecture) © City University London, Dept. of Computing Distributed Systems / 6 - 44 2.2 Object Creation (ctd.) It would be fairly costly if a factory interface had to be created for each object type. This would immediately double the number of interfaces in the distributed application. The life cycle service therefore defines the GenericFactory interface. It exports an operation by means of which it can be checked whether the Factory is able to create an object of a particular type (whose name is given as a key). A second operation allows clients to create an instance of the type whose name is given as a key. This overcomes the problem that type specific factories are not needed. In addition, resources can be managed for instances of different types that reside on one location. As a disadvantage, however, a type specific initialisation (which can be achieved within an object constructing operation of a specific factory) is not possible through this generic interface. © City University London, Dept. of Computing Distributed Systems / 6 - 45 2.2 Object Creation LifeCycle Service includes generic factory: interface GenericFactory { boolean supports(in Key k); Object create_object(in Key k, in NVP criteria) raises (NoFactory, InvalidCriteria, CannotMeetCriteria); }; Advantage: no type specific factories required. Disadvantage: No specific initialisations. © City University London, Dept. of Computing Distributed Systems / 6 - 46 Example import org.omg.CosNaming.*; import org.omg.CosLifeCycle.*; import org.omg.CORBA.*; //1) Instantiating the factory from an interoperable object reference stored in file String factoryIOR; factoryIOR = getFactoryIOR("genfac.ior"); org.omg.CORBA.Object genFacRef = orb.string_to_object(factoryIOR); GenericFactory fact = GenericFactoryHelper.narrow(genFacRef); //2) Using the factory to create an object // struct NameComponent { Istring id; Istring kind; }; NameComponent nc = new NameComponent("sBuyer::BuyerServer", "object interface"); NameComponent key[] = {nc}; NVP mycriteria[] = {}; org.omg.CORBA.Object objRef = fact.create_object(key, mycriteria); Buyer1Ref = BuyerHelper.narrow(objRef); © City University London, Dept. of Computing Distributed Systems / 6 - 47 2.3 Object Duplication The interface to duplicate objects is in LifeCycleObject. » The copy operation takes a FactoryFinder as a parameter. This factory finder defines the (set of) locations on which the copy should be created. Object types that are to be copied or moved around to other locations have to be subtypes of LifeCycleObject. To accomplish type specific implementations of the copy operation while retaining a unique and generic interface that is seen by clients, subtypes of LifeCycleObject redefine the copy operation. interface LifeCycleObject { LifeCycleObject copy (in FactoryFinder there) raises (NoFactory,...); ... }; © City University London, Dept. of Computing Distributed Systems / 6 - 48 2.3 Object Duplication The copying of an object cannot be implemented by the ORB. » It uses the factory to create a new object on the target machine. In this way, the problem of heterogeneous machine code of object implementations is resolved. Attribute values are transferred either » through parameters of the object constructing operation » through explicit operation invocations done after the object has been made. This way heterogeneity of data representation is resolved © City University London, Dept. of Computing Distributed Systems / 6 - 49 2.4 Object Deletion Objects that are created also have to be removed. In many object oriented programming languages this is done implicitly as the object is no longer referenced. This requires reference counting and garbage collection techniques which are not applicable to distributed objects because they are too expensive in a distributed setting! Deletion of an object is defined in the LifeCycleObject interface as well. To free the resources allocated by an object clients explicitly invoke the remove operation. interface LifeCycleObject { void remove() raises (NotRemovable); }; © City University London, Dept. of Computing Distributed Systems / 6 - 50 2.5 Object Migration Migration is the removal of an object implementation from one location to another location. The client view of migration is also defined by the LifeCycleObject interface by means of the move operation. Interfaces defining specific objects that inherit from LifeCycleObject redefine move in an application specific way! It is often possible to use the copy and the remove operation for that purpose. This, however, is not done generically, as more efficient ways may be possible in application specific situations. interface LifeCycleObject { void move(in FactoryFinder there) raises(NoFactory,NotMovable); }; © City University London, Dept. of Computing Distributed Systems / 6 - 51 2.6 What’s Missing: Replication No relationship is maintained between two objects once they have been copied. They therefore do not evolve together but are completely independent from each other. This means that the life cycle service does not support replication and therefore replication transparency is not support in the CORBA framework. There are integrations of particular CORBA products (Orbix, for instance) with replication middleware components (ISIS). These integrations, however, are not standardised and applications that use them will not be portable. The advantages of replication are that it allows for a higher load and also it supports fault tolerance because the state of an object can be recovered from a replica if an implementation has crashed. © City University London, Dept. of Computing Distributed Systems / 6 - 52 4 Summary Polylingual applications. IDL programming language bindings. Difference between centralised and distributed object lifecycle. CORBA Lifecycle Service. © City University London, Dept. of Computing Distributed Systems / 6 - 53 EXTRA GOODIES (Do read these…) © City University London, Dept. of Computing Distributed Systems / 6 - 54 3 Static vs. Dynamic Invocation Client Dynamic Invocation Client Stubs Object Implementation ORB Interface Server Skeleton Object Adapter ORB Core © City University London, Dept. of Computing Distributed Systems / 6 - 55 3.1 Generic Applications Example: Object Browser Generic applications use components whose types are not (yet) known. © City University London, Dept. of Computing Person Name: Celia Cruz Age: 56 Distributed Systems / 6 - 56 3.2 Static Invocation Advantages: » Requests are simple to define. » Availability of operations checked by programming language compiler. » Requests can be implemented fairly efficiently. Disadvantages: » Generic applications cannot be build. » Recompilation required after operation interface modification. © City University London, Dept. of Computing Distributed Systems / 6 - 57 3.3 Dynamic Invocation Interface Interface to create operation execution requests dynamically. Requests are objects. Attributes for operation name, parameters and results. Operations to » change operation parameters, » issue the request and » obtain the request results. © City University London, Dept. of Computing Distributed Systems / 6 - 58 3.4 Creation of Requests interface Object { ORBstatus create_request ( in Context ctx, in Identifier operation, in NVList arg_list, inout NamedValue result, out Request request in Flags req_flags ); ... }; © City University London, Dept. of Computing // // // // // // operation context operation to exec args of operation operation result new request object request flags Distributed Systems / 6 - 59 3.5 Synchronous Requests Server Client invoke © City University London, Dept. of Computing Distributed Systems / 6 - 60 3.6 Deferred Synchronous Requests Server Client send get_response © City University London, Dept. of Computing Distributed Systems / 6 - 61 3.7 Interface Repository Makes type information of interfaces available at run-time. Enables development of generic applications. Achieves type-safe dynamic invocations. Supports construction of interface browser. Used by ORB itself. © City University London, Dept. of Computing Distributed Systems / 6 - 62 3.8 Locating Interface Definitions Alternatives for locating interface definitions: Any interface inherits the operation InterfaceDef get_interface() from Object. Associative search using lookup_name. Navigation through the interface repository using contents and defined_in attributes. © City University London, Dept. of Computing Distributed Systems / 6 - 63 3.9 Example: Object Browser Person Name: Celia Cruz Age: 56 © City University London, Dept. of Computing Use interface repository to find out about object types at run-time Use dynamic invocation interface to obtain attribute values. Distributed Systems / 6 - 64 3.10 Object Browser Interaction Diagram Object InterfaceDef Request Request get_interface() name() describe_interface() create_request() invoke() create_request() invoke() © City University London, Dept. of Computing Distributed Systems / 6 - 65 4 Summary Polylingual applications. IDL programming language bindings. Difference between centralised and distributed object lifecycle. Dynamic vs static invocation CORBA Lifecycle Service. © City University London, Dept. of Computing Distributed Systems / 6 - 66