Chapter 27: Common Object Request Broker Architecture(CORBA): Part 2 Outline 27.1 Introduction 27.2 Static Invocation Interface (SII), Dynamic Invocation Interface (DII) and Dynamic Skeleton Interface (DSI) 27.3 BOAs, POAs and TIEs 27.4 CORBAservices 27.4.1 Naming Service 27.4.2 Security Service 27.4.3 Object Transaction Service 27.4.4 Persistent State Service 27.4.5 Event and Notification Services 27.5 EJBs and CORBAcomponents 27.6 CORBA vs. RMI 27.6.1 When to Use RMI 27.6.2 When to Use CORBA 27.6.3 RMI-IIOP
2002 Prentice Hall. All rights reserved.
Chapter 27: Common Object Request Broker Architecture(CORBA): Part 2 27.7
27.8 27.9
RMIMessenger Case Study Ported to RMI-IIOP 27.7.1 ChatServer RMI-IIOP Implementation 27.7.2 ChatClient RMI-IIOP Implementation 27.7.3 Compiling and Running the ChatServer and ChatClient Future Directions Internet and World Wide Web Resources
2002 Prentice Hall. All rights reserved.
27.1
Introduction
• JavaIDL is the first step into the world of CORBA and distributed systems. • Understanding of CORBA concepts at both the low level (i.e., object adapters) and high level (i.e., CORBAservices and CORBAcomponents) is important.
2002 Prentice Hall. All rights reserved.
27.2 Static Invocation Interface (SII), Dynamic Invocation Interface (DII) and Dynamic Skeleton Interface (DSI) • Two ways to invoke a request: –
statically – using Static Invocation Interface (SII) –
–
dynamically – using Dynamic Invocation Interface (DII) – –
•
relies on creating a request through invoking a static method in a stub – stub generated from compile-time definition of an object type (IDL interface) and object operations (methods within IDL interface) programmatically creates and send invocation request directly to ORB without assistance of stub developers responsible for guaranteeing sending proper type and number of arguments to invocation
Server unaware of process that created the request.
2002 Prentice Hall. All rights reserved.
27.2 Static Invocation Interface (SII), Dynamic Invocation Interface (DII) and Dynamic Skeleton Interface (DSI) (cont.) • Interface Repository (IR)
–
contains descriptive information about distributed objects: • • • • • •
•
modules available interfaces defined names of operations defined within interfaces argument types return types exceptions raised
Steps needed to make DII call: • • • • • •
Obtain object reference to server object Look up desired method in Interface Repository Build argument list using IR’s OperationDef Create and initialize Request object Invoke Request and wait for call to unblock (return) Get results
2002 Prentice Hall. All rights reserved.
27.2 Static Invocation Interface (SII), Dynamic Invocation Interface (DII) and Dynamic Skeleton Interface (DSI) (cont.) • Java 1.3 does not ship with an Interface Repository • Steps needed to make DII call (without using Interface Repository): • • • •
Obtain object reference to server object Create and initialize a Request object Invoke Request and wait for call to unblock (return) Get results
2002 Prentice Hall. All rights reserved.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
// SystemClockClient.java // Client that uses DII to request the system time from a servant. package com.deitel.advjhtp1.idl.dii;
Fig. 27.1 SystemClockClien t modified to support DII
// Java core packages import java.text.DateFormat; import java.util.*; // Java extension packages import javax.swing.JOptionPane; // OMG import import import
Outline
Line 20
CORBA packages org.omg.CORBA.ORB; org.omg.CosNaming.*; org.omg.CosNaming.NamingContextPackage.*;
Line 21 Line 26
public class SystemClockClient implements Runnable { // object reference to desired server private org.omg.CORBA.Object timeServer; private ORB orb; used to connect client
holds reference to remote server to server and to create support objects for invocation to server
// initialize client public SystemClockClient( String[] params ) throws Exception { connectToTimeServer( params ); obtains reference to startTimer(); }
server
2002 Prentice Hall. All rights reserved.
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
// use NameService to connect to time server private void connectToTimeServer( String [] params ) throws org.omg.CORBA.ORBPackage.InvalidName, org.omg.CosNaming.NamingContextPackage.InvalidName, NotFound, CannotProceed { // Connect to the SystemClock server orb = ORB.init( params, null );
Outline Fig. 27.1 SystemClockClien t modified to support DII
org.omg.CORBA.Object corbaObject = orb.resolve_initial_references( "NameService" ); NamingContext naming = NamingContextHelper.narrow( corbaObject ); // Resolve the object reference in naming NameComponent nameComponent = new NameComponent( "TimeServer", "" ); NameComponent path[] = { nameComponent }; timeServer = naming.resolve( path ); } // start timer thread private void startTimer() { Thread thread = new Thread( this ); thread.start(); } // talk to server on a regular basis and display the results public void run() { long time = 0; Date date = null; DateFormat format = DateFormat.getTimeInstance( DateFormat.LONG );
2002 Prentice Hall. All rights reserved.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
Outline
String timeString = null; int response = 0; org.omg.CORBA.Request request = timeServer._request( "currentTimeMillis" ); request.set_return_type( orb.get_primitive_tc( org.omg.CORBA.TCKind.tk_longlong ) ); while( true ) {
Fig. 27.1 SystemClockClien t modified to support DII Request object used by client to call server Lines 68-69
// invoke method currentTimeMillis using the request object // time = timeServer.currentTimeMillis(); original method invocation Line 77 request.invoke(); invoke request on server // get time value from request object time = request.result().value().extract_longlong(); date = new Date( time ); timeString = format.format( date );
Line 78 response obtain server Line 81
response = JOptionPane.showConfirmDialog( null, timeString, "SystemClock Example", JOptionPane.OK_CANCEL_OPTION ); if ( response == JOptionPane.CANCEL_OPTION ) break; } System.exit( 0 ); }
2002 Prentice Hall. All rights reserved.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
// main method to execute client application public static void main( String args[] ) { // create client try { new SystemClockClient( args ); } // process exceptions that occur while client executes catch ( Exception exception ) { System.out.println( "Exception thrown by SystemClockClient:" ); exception.printStackTrace(); }
Outline Fig. 27.1 SystemClockClien t modified to support DII
} }
2002 Prentice Hall. All rights reserved.
27.2 Static Invocation Interface (SII, Dynamic Invocation Interface (DII) and Dynamic Skeleton Interface (DSI) (cont.) • Using Interface Repository enables flexibility at runtime to discover more about types available in a distributed system. • IR functions as a distributed version of the Java reflection mechanism. • JavaIDL is not a complete implementation of CORBA. – when designing a distributed system with CORBA, use a third party implementation: • commercial vendors implementations • open-source implementations
2002 Prentice Hall. All rights reserved.
27.3
BOAs, POAs and TIEs
• Object adapter – stands between a distributed object and its ORB – enables clients to access ORB services: • IOR generation • security • activation/deactivation
• OMG specified two adapter types: – Basic Object Adapter (BOA) • vague definition of an adapter which led to inconsistencies between different vendors’ implementations
– Portable Object Adapter (POA) • more widely used, even though more complex than BOAs 2002 Prentice Hall. All rights reserved.
27.3
BOAs, POAs and TIEs (cont.)
• POA connects an object reference to developerwritten code using code found in IDL generated skeleton. – allow fine-grained control
• Distributed objects inherit from a POA base definition generated by IDL compiler – enables distributed object to be usable by a POA, – enables POA to control all access to servant through policies
2002 Prentice Hall. All rights reserved.
27.3
BOAs, POAs and TIEs (cont.)
• POA policies: – ImplicitObjectActivation, • tells POA outside object created servant and activated it
– IDAssignmentPolicy, and • determines who is responsible for assigning a unique ID to a given servant
– RequestProcessingPolicy. • uses object id either to find matching servant or invoke default service that uses object id to perform lookup in database
• Policy combinations provide POAs with finegrained control over one or many servants.
2002 Prentice Hall. All rights reserved.
27.3
BOAs, POAs and TIEs (cont.)
• Another way for developer to us a POA is to wrap their servants in a TIE. – enables interaction with a POA without having servant’s object implementation inherit structure from POAImpl. – servant can inherit from other base classes freely
2002 Prentice Hall. All rights reserved.
27.4 •
•
CORBAservices
CORBAservices define base services and a support structure useful to a wide range of applications. Five most commonly used services: 1. 2. 3. 4. 5.
Naming Service Security Service Object Transaction Service Persistent State Service Event and Notification Services
2002 Prentice Hall. All rights reserved.
27.4.1
Naming Service
• Associates name objects with arbitrary value (known as name bindings). • A path to a name binding consists of zero or more naming contexts (a collection of unique name bindings). • Resolving a name binding returns object associated with name. • Binding a name creates association between a name and an object. • Multiple name bindings can point to a single object. 2002 Prentice Hall. All rights reserved.
27.4.2 •
Security Service
Consists of two levels –
Level 1 •
• •
provides basic security for 1. user authentication, 2. invocation security, and 3. availability of authentication principals to security-aware applications allows applications to ignore system-security requirements requires support for no delegation and single delegation models
2002 Prentice Hall. All rights reserved.
27.4.2 –
Security Service (cont.)
Level 2 •
is everything level 1 provides in addition to: 1. more fine-grained user authentication 2. greater invocation security 3. auditing 4. finer control over secure invocations 5. delegation 6. administrators can set security policies 7. discovery of security policies by security-aware applications 8. discovery of security policies by ORBs and other services
2002 Prentice Hall. All rights reserved.
27.4.3 •
Object Transaction Service
Enables CORBA objects to execute as parts of distributed transactions. –
a transaction describes a collection of interactions where multiple users may access and/or modify data. •
acronym ACID describes four standard requirements for reliable transactions: 1. Atomic – completion of numerous steps must be conducted as one, otherwise each step must be undone. 2. Consistent – effects of transaction are repeatable and predictable. 3. Isolated – transaction not interrupted from outside and gives no indication if execution is proceeding serially or concurrently. 4. Durable – transaction results are persistent.
2002 Prentice Hall. All rights reserved.
27.4.3 –
Object Transaction Service (cont.)
transactions complete in one of two ways: 1. committed • changes are made to persist 2. rolled back • changes made to data are discarded
–
POAs dictate transaction types supported by servants • • •
shared transactions unshared transactions shared and unshared transactions
2002 Prentice Hall. All rights reserved.
27.4.3
Object Transaction Service (cont.)
• Concepts of transactional clients, transactional objects and recoverable objects define the OTS. – transactional clients interact with OTS to create and commit or rollback a transaction – transaction objects’ behaviors vary when invoked within a transaction (object’s data not recoverable) – recoverable object is a transactional object in which data is recoverable (maintain their data and capable of restoring their lost state)
• Java Transaction Service (JTS) is Java implementation of distributed transaction service – uses CORBA OTS specification to define protocol 2002 Prentice Hall. All rights reserved.
27.4.4
Persistent State Service
• Persistent State Service (PSS) stores and retrieves objects. • Abstracts interaction between objects and datastores. • Persistent State Definition Language (PSDL) defines a distributed object schema in a portable fashion. – PSDL is a superset of IDL • defines two new constructs – storagetype – storagehome
2002 Prentice Hall. All rights reserved.
27.4.4
Persistent State Service (cont.)
– contains two definition types: • abstract definition – define portable definition of the persistable state of a CORBA object • concrete definition
2002 Prentice Hall. All rights reserved.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
// The schema for a domain object. This is the abstract definition // needed by the PSS. The concrete definition of Customer is below. abstract storagetype Customer { // The accountNumber is our primary key readonly state string accountNumber; state string name; };
Outline
Fig. 27.2 Persistent State Definition Language declares abstract storagetype // The factory to be used to retrieve Customer objects declares declares readable/writable a read-only accountNumber example. abstract storagehome CustomerHome of Customer { name keyword method statewill create persistent Customers // using The creation Customer create( in string accountNumber ); creates Customers to notify PSDL compiler of Line 3using method }; create, each with which fields to persist accountNumber // Our factory finder. Use the CustomerDirectory to Line as 5 primary key // find any factories used by the system to create // domain objects like Customer catalog CustomerDirectory { provides CustomerHome customerHome; };
Line 6 Line 12
// This is the concrete declaration of the Customer defined // above. These declarations are empty as we are not adding // any addition structure to Customer or its factory. storagetype CustomerImpl implements Customer {}; storagehome CustomerHomeImpl of CustomerImpl implements CustomerHome {};
2002 Prentice Hall. All rights reserved.
27.4.5
Event and Notification Services
• Event Service defines mechanism that decouples delivery of events (messages) from source of events. – no predefined event types in specification – keeps track of action events and event listeners
• Supplier creates events that are processed by a consumer. • In push model, supplier sends event messages asynchronously to all consumers registered to receive messages. • In pull model, consumer polls supplier for events. 2002 Prentice Hall. All rights reserved.
27.4.5
Event and Notification Services (cont.)
• Notification Service is a direct extension of the Event Service. – objects can create and destroy event channels arbitrarily, and can filter output using Filter Objects and Object Constraint Language
2002 Prentice Hall. All rights reserved.
27.4.5 •
Event and Notification Services (cont.)
Standard flow of a StructuredEvent: •
finding object reference to Notificaion Service (instance of EventChannelFactory) • EventChannelFactory creates an EventChannel • supplier asks EventChannel to return SupplierAdmin object • SupplierAdmin returns a Consumer proxy (such as StructuredProxyPushConsumer) to an event channel • access to distributed events (through push or pull models) is accessible through proxy
2002 Prentice Hall. All rights reserved.
27.4.5
Event and Notification Services (cont.)
C oncep tua lly, a Sup plie r send s a n Eve nt to a C onsume r. Supp lier
Co nsumer
Eve nt
An EventChannel deco up les the Supp lier from the Consumer. Supp lier
Eve nt
EventChannel
Eve nt
Co nsumer
Ad ding a ProxyConsumer a nd ProxySupplier enables further d ecoupling a nd make s it p ossible to sup po rt bo th the p ush and pull mod els. Supp lier Eve nt
ProxyConsumer Event EventChannel Event ProxySupplier
Co nsumer Eve nt
Fig. 27.3 Supplier-to-consumer flow using the Event/Notification Service.
2002 Prentice Hall. All rights reserved.
27.5
EJBs and CORBAcomponents
• CORBA Component Model (CCM) Request for Proposal (RFP) recommends the JavaBeans component model as basis of a server-side framework. • CORBAcomponents based on Component Implementation Framework (CIF) architecture. • CIF defines superset of Persistent State Definition Language called Component IDL (CIDL) • CIDL is component model for CORBA objects and a container-programming model where CORBA components exist at runtime 2002 Prentice Hall. All rights reserved.
27.5
EJBs and CORBAcomponents (cont.)
IDL keywords to support the C O RBA C omponent Model (C C M)
component
home
provides
consumes emits
import local
setRaises supports
finder multiple getRaises primaryKey Fig. 27.4IDL keywords to support the C ORBA C omponent Model.
2002 Prentice Hall. All rights reserved.
typeId typePrefix
27.5
EJBs and CORBAcomponents (cont.)
• Component Interface Definition Language (CIDL) is a superset of Persistent State Definition Language. – defines • components in a way that enables automatic generation of component’s persistence code. • component implementation • state management
– compiled with a CIDL compiler
• Developers organize components as an assembly with a descriptor. – describes how components are deployed – extension of Open Software Description (OSD) Format 2002 Prentice Hall. All rights reserved.
27.5
EJBs and CORBAcomponents (cont.)
• A Container class creates a containment hierarchy grouping components and other containers together. • Container programming model is a runtime environment in which component implementations use their enclosing containers to access various services the container provides.
2002 Prentice Hall. All rights reserved.
27.5 •
EJBs and CORBAcomponents (cont.)
Four areas make up CCM container programming model: 1. External types • interfaces seen by client wanting to communicate with component 2. Container types • API component uses to communicate with runtime container 3. Container Implementation types • different containers have different relationships with surrounding system. Three types: stateless, conversational, and durable. Each type defines its system support 4. Component Category • where a component fits in overall framework
2002 Prentice Hall. All rights reserved.
27.5
EJBs and CORBAcomponents (cont.)
• Using a container’s internal interfaces, a component has full access to services a container supports – Container defines APIs for: • • • • •
component security persistence transactions events lifecycle
– Component implements call-back interfaces to allow container-to-component communication.
2002 Prentice Hall. All rights reserved.
27.5
EJBs and CORBAcomponents (cont.)
• Components can be either – transient, or • can only be created by factories • do not have primary keys
– persistent • can be created by factories and located by finders • have primary keys • support two forms of persistence – container managed – component managed
2002 Prentice Hall. All rights reserved.
27.5 C omponent Type
Service
EJBs and CORBAcomponents (cont.) Desc rip tion
• • •
•
Does not maintain state information (completely stateless) Does not have a unique id (primary key) Implements needed behavior calculateInterest, (e.g., addItemToShoppingCart, etc.) Can use transactions, is not included in the current transaction
Session
• • • • •
Maintains internal-state information Has a unique id that is usable only by its container Implements needed behavior Can use transactions, but is not included in the current transaction Maps to Session EJBs
Entity
• • • •
Container- or component-managed persistent state Has a unique id (primary key) Implements needed behavior that is optionally transactional Maps to Entity EJBs
Process
•
Container-managed or component-managed persistent state that is inaccessible to clients Container-managed or component-managed persistence of the component’s primary key (identity) with visibility of the primary key through user-defined methods Implements needed behavior and the behavior is optionally transactional
• •
Fig. 27.5C O RBA
c omponent types and d esc riptions.
2002 Prentice Hall. All rights reserved.
27.5 •
EJBs and CORBAcomponents (cont.)
Activation and passivation are actions around invocation boundaries of an object operation. –
activation lifecycle 1. 2. 3. 4.
–
request arrives to ORB to invoke operation on object ORB sends request to POA POA sends request to container managing component container activates object
passivation policies defined by component’s deployment information
2002 Prentice Hall. All rights reserved.
27.5
EJBs and CORBAcomponents (cont.)
• In distributed systems, clients don’t create remote objects. Clients discover remote objects. – discovery through file containing object’s IOR – discovery through Naming Service
• Factories (ComponentHome instances) of remote systems create objects for their corresponding systems. – component definition must define component factory – if component persistent, must define find method using component’s primary key
2002 Prentice Hall. All rights reserved.
27.5
EJBs and CORBAcomponents (cont.)
• CORBAcomponents use subset of CORBAservices for Component Implementation Framework. – Security Service • every component may have own security requirement – defined in component’s deployment descriptor • container must keep track of active policies and apply them
– Object Transaction Service (lite version) • container can control transaction boundaries • component can control transaction boundaries
– Persistent State Service • container-managed persistence, PSS transparent to component – not ideal for all situations • component-managed persistence, should still use PSS to save state
2002 Prentice Hall. All rights reserved.
27.5
EJBs and CORBAcomponents (cont.)
– Notification Service • accessed indirectly • container mediates use of event service by component • container does not preclude direct use of Notification Service – component developers are encouraged to define events in IDL as way of keeping component’s functional description in one location • keywords: – publishes • any number of consumers can subscribe to an event • methods declared with publishes expected to be part of shared interface of component – emits • only one consumer can subscribe to an event • expected to be private channel used internally by system 2002 Prentice Hall. All rights reserved.
1 2 3 4 5 6 7 8
// Our Customer can send two events: // creditEvent if the customer's credit limit has been exceeded // and internalStateEvent if the some data in the customer // has not been updated properly component Customer { publishes PropertyEvent creditEvent; emits InvariantEvent internalStateEvent; };
allows any number of subscribers to an event allows one subscriber to an event
Outline Fig. 27.6 Customer component IDL definition demonstrating keywords publishes and emits for issuing events. Line 6 Line 7
2002 Prentice Hall. All rights reserved.
27.5
EJBs and CORBAcomponents (cont.)
• CCM and EJB models are similar. • CCM specification defines two component levels – basic • • • •
mirrors EJB model almost exactly single threaded uses security, transaction and persistence services only exposes only single interface
– extended • can expose multiple interfaces • advanced store types allows components to be properly persisted • supports use of Event Services
• Sun and OMG worked closely to ensure EJB model is CCM architecture subset. 2002 Prentice Hall. All rights reserved.
27.6
CORBA vs. RMI
• CORBA is comprehensive view of distributed systems architecture. • RMI describes only communication proxies and protocols between client object and server object.
2002 Prentice Hall. All rights reserved.
27.6.1
When to Use RMI
• RMI suitable for smaller distributed applications in which scalability, architecture, heterogeneity, and extensibility are not major concerns. • Mapping of RMI and RMI capabilities to OMA encompasses only Applications Objects and the ORB. • RMI does not define Quality of Service or asynchronous invocations. • RMI does not offer POA or range of control offered by POA. • RMI has dynamic class loading. CORBA places implementation burden on clients. 2002 Prentice Hall. All rights reserved.
27.6.1
When to Use RMI (cont.)
• RMI allows objects to participate in distributed systems consistently and predictably. • RMI is a natural choice for distributed systems built in Java. • A pure Java-distributed system needs to be considered from an architectural perspective where distributed issues can be discovered and resolved before the implementation issues are decided.
2002 Prentice Hall. All rights reserved.
27.6.2
When to Use CORBA
• CORBA defines and provides implementations to many common requirements for most complex distributed systems: – – – – –
architecture Quality of Service (QoS) Scalability Heterogeneity Extensibility
2002 Prentice Hall. All rights reserved.
27.6.3
RMI-IIOP
• SUN and IBM implemented RMI-over-IIOP (RMI-IIOP) to replace RMI’s underlying communication protocol (Java Remote Method Protocol or JRMP). • Inprise, Netscape, Oracle, Sun and IBM specified reverse mapping of Java-to IDL. – Mapping limitations: • Constants can be of primitive types or of class java.lang.String only • IDL normally does not support overloading of method names. • A class cannot inherit a method with same signature from two different interfaces. • Interfaces and value types must be public. • Compiler considers packages and interface names are not casesensitive.
2002 Prentice Hall. All rights reserved.
27.6.3
RMI-IIOP (cont.)
– runtime limitations: • sending a tree graph from ORB to ORB may be problematic if multiple nodes point to one object • CORBA does not define distributed garbage collection • Casting stubs may not work properly, so using the static method narrow of class java.rmi.PortableRemoteObject is encouraged. • RMI downloads the stubs needed by client, CORBA does not.
2002 Prentice Hall. All rights reserved.
27.6.3
RMI-IIOP (cont.)
– steps involved in writing distributed application using RMIIIOP: • use javax.rmi.PortableRemoteObject instead of using java.rmi.UnicastRemoteObject • use JNDI (Java Naming and Directory Interface) instead of RMI Registry • do not downcast remote objects to subclass types; use method narrow of class PortableRemoteObject to cast distributed objects as subclass types
2002 Prentice Hall. All rights reserved.
27.7
RMIMessenger Case Study Ported to RMI-IIOP
• Porting RMI messenger example (Chapter 13) to RMI-IIOP is easier than porting application to CORBA. – remote interfaces remain same – support classes remain same – new implementations for • ChatServer remote interface (ChatServerImpl), • ChatServerAdministrator • MessageManager interface (RMIIIOPMessageManager) • DeitelMessenger
2002 Prentice Hall. All rights reserved.
27.7.1
ChatServer RMI-IIOP
Implementation • ChatServerImpl
– implements ChatServer remote interface • subclass of class javax.rmi.PortableRemoteObject
– does not implement method register – handles registration with name services
2002 Prentice Hall. All rights reserved.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
// ChatServerImpl.java // ChatServerImpl implements the ChatServer and StoppableChatServer // remote interfaces using RMI over IIOP. package com.deitel.messenger.rmi_iiop.server; // Java core packages import java.io.*; import java.util.*; import java.net.MalformedURLException; import java.rmi.*; // Java extension packages import javax.rmi.*; // Deitel packages import com.deitel.messenger.rmi.ChatMessage; import com.deitel.messenger.rmi.client.ChatClient; import com.deitel.messenger.rmi.server.*;
Outline Fig. 27.7 ChatServerImpl implements the Deitel messenger ChatServer using RMI-IIOP. Line 20 Line 21
public class ChatServerImpl extends PortableRemoteObject implements ChatServer, StoppableChatServer {
subclass of javax.rmi.PortableRemoteObject, base class for RMI-IIOP remote objects
// Set of ChatClient references which is private Set clients = new HashSet();
interfaces remain unchanged for implementation
// construct new ChatServerImpl public ChatServerImpl() throws RemoteException { super(); }
2002 Prentice Hall. All rights reserved.
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
// register new ChatClient with ChatServer public void registerClient( ChatClient client ) throws RemoteException { // add client to Set of registered clients synchronized( clients ) { clients.add( client ); } System.out.println( "Registered Client: " + client ); } // end method registerClient
Outline Fig. 27.7 ChatServerImpl implements the Deitel messenger ChatServer using RMI-IIOP.
// unregister client with ChatServer public void unregisterClient( ChatClient client ) throws RemoteException { // remove client from Set of registered clients synchronized( clients ) { clients.remove( client ); } System.out.println( "Unregistered Client: " + client ); } // end method unregisterClient // post new message to ChatServer public void postMessage( ChatMessage message ) throws RemoteException { Iterator iterator = null; // get Iterator for Set of registered clients synchronized( clients ) { iterator = new HashSet( clients ).iterator();
2002 Prentice Hall. All rights reserved.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
} // send message to every ChatClient while ( iterator.hasNext() ) { ChatClient client = ( ChatClient ) iterator.next(); client.deliverMessage( message ); } } // end method postMessage // notify each client that server is shutting down and // terminate server application public void stopServer() throws RemoteException { System.out.println( "Terminating server ..." );
Outline Fig. 27.7 ChatServerImpl implements the Deitel messenger ChatServer using RMI-IIOP.
Iterator iterator = null; // get Iterator for Set of registered clients synchronized( clients ) { iterator = new HashSet( clients ).iterator(); } // send serverStopping message to every ChatClient while ( iterator.hasNext() ) { ChatClient client = ( ChatClient ) iterator.next(); client.serverStopping(); System.err.println( "Disconnected: " + client ); } // create Thread to terminate application after // stopServer method returns to caller Thread terminator = new Thread( new Runnable() {
2002 Prentice Hall. All rights reserved.
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
// sleep for 5 seconds, print message and terminate public void run() { // sleep try { Thread.sleep( 5000 ); } // ignore InterruptedExceptions catch ( InterruptedException exception ) {} System.err.println( "Server terminated" ); System.exit( 0 );
Outline Fig. 27.7 ChatServerImpl implements the Deitel messenger ChatServer using RMI-IIOP.
} } ); terminator.start(); // start termination thread } // end method stopServer }
2002 Prentice Hall. All rights reserved.
27.7.1 ChatServer RMI-IIOP Implementation (cont.) • ChatServerAdministrator – utility program for starting and stopping RMI-IIOP ChatServer implementation
2002 Prentice Hall. All rights reserved.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
// ChatServerAdministrator.java // ChatServerAdministrator is a utility for starting and stopping // the RMI-IIOP ChatServer implementation. package com.deitel.messenger.rmi_iiop.server; // Java core packages import java.rmi.*; import java.rmi.activation.*; import java.util.*; // Java extension packages import javax.rmi.*; import javax.naming.*;
Outline Fig. 27.8 ChatServerAdmini strator application for starting and stopping RMIIIOP ChatServer.
// Deitel packages import com.deitel.messenger.rmi.server.StoppableChatServer;
Line 27
public class ChatServerAdministrator {
Lines 30 and 35
// set up ChatServer object private static void startServer() creates { // register ChatServer in Naming Service try {
instance of ChatServerImpl
// create ChatServerImpl object ChatServerImpl chatServerImpl = new ChatServerImpl(); register ChatServer
with naming service
// create InitialContext for naming service Context namingContext = new InitialContext(); System.err.println( "Binding server to naming service.." ); // bind ChatServerImpl object to naming service namingContext.rebind( "ChatServer", chatServerImpl );
2002 Prentice Hall. All rights reserved.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
System.out.println( "Server bound to naming service" ); } // end try
Fig. 27.8 ChatServerAdmini strator application for starting and stopping RMIIIOP ChatServer.
// handle exception registering ChatServer catch ( NamingException namingException ) { namingException.printStackTrace(); System.exit( 1 ); } // handle exception creating ChatServer catch ( RemoteException remoteException ) { remoteException.printStackTrace(); System.exit( 1 ); }
Line 62 Lines 65-66
} // end method startServer // terminate server private static void terminateServer() { // look up and terminate ChatServer try {
Outline
create InitialContext
// create naming Context for looking up server Context namingContext = new InitialContext();
obtain remote reference
// find ChatServer remote object Object remoteObject = namingContext.lookup( "ChatServer" );
2002 Prentice Hall. All rights reserved.
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102
// narrow remoteObject to StoppableChatServer StoppableChatServer chatServer = ( StoppableChatServer ) PortableRemoteObject.narrow( remoteObject, StoppableChatServer.class ); // stop ChatServer chatServer.stopServer(); // remove ChatServer from Naming Service namingContext.unbind( "ChatServer" ); } // end try // handle exception looking up ChatServer catch ( NamingException namingException ) { namingException.printStackTrace(); }
Outline
Fig. 27.8 ChatServerAdmini strator application for starting remove from Naming Service and stopping RMIuse method narrow to cast ChatServer. reference to IIOP StoppableChatServer type Lines 69-71 Line 77
// handle exception communicating with ChatServer catch ( RemoteException remoteException ) { remoteException.printStackTrace(); } } // end method terminateServer // launch ChatServerAdministrator application public static void main( String args[] ) { // check command-line arguments and start or stop server if ( args[ 0 ].equals( "start" ) ) startServer(); else if ( args[ 0 ].equals( "stop" ) ) terminateServer();
2002 Prentice Hall. All rights reserved.
103 104 105 106 107 108 109
// print usage information else System.err.println( "Usage: java ChatServerAdministrator start | stop" ); } // end method main }
Binding server to naming service... Server bound to naming service Registered Client: IOR:0000000000000040524d493a636f6d2e64656974656c2e6d657373656e6765722e726 d692e636c69656e742e43686174436c69656e743a30303030303030303030303030303030 00000000010000000000000054000101000000000d3139322e3136382e312e3435000005e 000000018afabcaff00000002243bba8f0000000800000001000000000000000100000001 000000140000000000010020000000000001010000000000 Registered Client: IOR:0000000000000040524d493a636f6d2e64656974656c2e6d657373656e6765722e726 d692e636c69656e742e43686174436c69656e743a30303030303030303030303030303030 00000000010000000000000054000101000000000d3139322e3136382e312e3435000005e 500000018afabcaff00000002243bbbed0000000800000001000000000000000100000001 000000140000000000010020000000000001010000000000 Registered Client: IOR:0000000000000040524d493a636f6d2e64656974656c2e6d657373656e6765722e726 d692e636c69656e742e43686174436c69656e743a30303030303030303030303030303030 00000000010000000000000054000101000000000d3139322e3136382e312e3435000005e a00000018afabcaff00000002243bbd5c0000000800000001000000000000000100000001 000000140000000000010020000000000001010000000000
Outline Fig. 27.8 ChatServerAdmini strator application for starting and stopping RMIIIOP ChatServer.
2002 Prentice Hall. All rights reserved.
Unregistered Client: IOR:0000000000000040524d493a636f6d2e64656974656c2e6d657373656e6765722e726 d692e636c69656e742e43686174436c69656e743a30303030303030303030303030303030 00000000010000000000000054000101000000000d3139322e3136382e312e3435000005e 000000018afabcaff00000002243bba8f0000000800000001000000000000000100000001 000000140000000000010020000000000001010000000000 Terminating server ... Disconnected: IOR:0000000000000040524d493a636f6d2e64656974656c2e6d657373656e6765722e726 d692e636c69656e742e43686174436c69656e743a30303030303030303030303030303030 00000000010000000000000054000101000000000d3139322e3136382e312 e3435000005e500000018afabcaff00000002243bbbed0000000800000001000000000000 000100000001000000140000000000010020000000000001010000000000 Disconnected: IOR:0000000000000040524d493a636f6d2e64656974656c2e6d657373656e6765722e726 d692e636c69656e742e43686174436c69656e743a30303030303030303030303030303030 00000000010000000000000054000101000000000d3139322e3136382e312e3435000005e a00000018afabcaff00000002243bbd5c0000000800000001000000000000000100000001 000000140000000000010020000000000001010000000000 Server terminated
Outline Fig. 27.8 ChatServerAdmini strator application for starting and stopping RMIIIOP ChatServer.
2002 Prentice Hall. All rights reserved.
27.7.2
ChatClient RMI-IIOP
Implementation
• implement ChatClient RMI-IIOP messenger: – provide RMI-IIOP implementation of interface MessageManager – create new DeitelMessenger application for launching ClientGUI with new MessageManager implementation
2002 Prentice Hall. All rights reserved.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
// RMIIIOPMessageManager.java // RMIIIOPM22essageManager implements the ChatClient remote // interface and manages incoming and outgoing chat messages // using RMI over IIOP. package com.deitel.messenger.rmi_iiop.client; // Java core packages import java.awt.*; import java.awt.event.*; import java.rmi.*; import java.rmi.server.*; import java.util.*; // Java extension packages import javax.rmi.*; import javax.naming.*;
Outline Fig. 27.9 RMIIIOPMessage Manager implements the ChatClient and MessageManager interfaces using RMI-IIOP.
Line 24 extends PortableRemoteObject
// Deitel packages import com.deitel.messenger.*; import com.deitel.messenger.rmi.client.ChatClient; import com.deitel.messenger.rmi.ChatMessage; import com.deitel.messenger.rmi.server.ChatServer; public class RMIIIOPMessageManager extends PortableRemoteObject implements ChatClient, MessageManager { // listeners for incoming messages and disconnect notifications private MessageListener messageListener; private DisconnectListener disconnectListener; // ChatServer for sending and receiving messages private ChatServer chatServer; // RMIMessageManager constructor public RMIIIOPMessageManager() throws RemoteException {}
2002 Prentice Hall. All rights reserved.
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
// connect to ChatServer public void connect( MessageListener listener ) throws Exception { // create naming Context for looking up server Context namingContext = new InitialContext();
Outline
Fig. 27.9 RMIIIOPMessage Manager implements the // find ChatServer remote object obtain remote reference to ChatClient and Object remoteObject = RMI-IIOP ChatServer namingContext.lookup( "ChatServer" ); MessageManager interfaces using chatServer = ( ChatServer ) PortableRemoteObject.narrow( RMI-IIOP. remoteObject, ChatServer.class ); // register client with ChatServer to receive messages chatServer.registerClient( this );
Lines 38-57
// set listener for incoming messages messageListener = listener; } // end method connect // disconnect from ChatServer public void disconnect( MessageListener listener ) throws Exception { if ( chatServer == null ) return; chatServer.unregisterClient( this ); messageListener = null; // notify listener of disconnect fireServerDisconnected( "" );
2002 Prentice Hall. All rights reserved.
71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
} // end method disconnect // send ChatMessage to ChatServer public void sendMessage( String fromUser, String message ) throws Exception { if ( chatServer == null ) return; // create ChatMessage with message text and user name ChatMessage chatMessage = new ChatMessage( fromUser, message );
Outline Fig. 27.9 RMIIIOPMessage Manager implements the ChatClient and MessageManager interfaces using RMI-IIOP.
// post message to ChatServer chatServer.postMessage( chatMessage ); }
// end method sendMessage
// process delivery of ChatMessage from ChatServer public void deliverMessage( ChatMessage message ) throws RemoteException { if ( messageListener != null ) messageListener.messageReceived( message.getSender(), message.getMessage() ); } // process server shutting down notification public void serverStopping() throws RemoteException { chatServer = null; fireServerDisconnected( "Server shut down." ); }
2002 Prentice Hall. All rights reserved.
106 107 108 109 110 111 112 113 114 115 116 117 118 119
// register listener for disconnect notifications public void setDisconnectListener( DisconnectListener listener ) { disconnectListener = listener; } // send disconnect notification private void fireServerDisconnected( String message ) { if ( disconnectListener != null ) disconnectListener.serverDisconnected( message ); } }
Outline Fig. 27.9 RMIIIOPMessage Manager implements the ChatClient and MessageManager interfaces using RMI-IIOP.
2002 Prentice Hall. All rights reserved.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
// DeitelMessenger.java // DeitelMessenger uses ClientGUI and RMIIIOPMessageManager to // implement an RMI over IIOP chat client. package com.deitel.messenger.rmi_iiop.client; // Java core packages import java.rmi.RMISecurityManager; // Deitel packages import com.deitel.messenger.*; public class DeitelMessenger {
Outline
Fig. 27.10 DeitelMessenger creates a ClientGUI and Create instance of class RMIIIOPMessageMa RMIIIOPMessageManager nager to launch the RMI-IIOP messenger Exception client.
// launch DeitelMessenger application public static void main( String args[] ) throws { // create RMIIIOPMessageManager for communicating with server MessageManager messageManager = new RMIIIOPMessageManager(); // configure and display chat window ClientGUI clientGUI = new ClientGUI( messageManager ); clientGUI.setSize( 300, 400 ); clientGUI.setResizable( false ); clientGUI.setVisible( true );
Line 18 Line 21
} }
create GUI instance using RMIIIOPMessageManager instance
2002 Prentice Hall. All rights reserved.
27.7.3
Compiling and Running the ChatServer and ChatClient
• Using java compiler compile – – – –
ChatServerImpl, ChatServerAdministrator, RMIIIOPMessageManager, and DeitelMessenger.
• Using rmic tool and –iiop command-line option generate RMI-IIOP stub classes – ChatServerImpl • rmic –iiop com.deitel.messenger.rmi_iiop.server.ChatServerImpl
– RMIIIOPMessageManager • rmic –iiop com.deitel.messenger.rmi_iiop.server.RMIIOPMessageManager
2002 Prentice Hall. All rights reserved.
27.7.3
Compiling and Running the ChatServer and ChatClient (cont.)
• Start tnameserv – tnameserv –ORBInitialPort 1050
• Start ChatServerAdministrator –
java –Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory –Djava.naming.provider.url=iiop://localhost:1050 com.deitel.messenger.rmi_iiop.server.ChatServerAdministrator start
• Start ChatServer –
java –Djava.naming.factory.initial=com.sun.jndi.cosnaming.CNCtxFactory –Djava.naming.provider.url=iiop://localhost:1050 com.deitel.messenger.rmi_iiop.client.DeitelMessenger
2002 Prentice Hall. All rights reserved.
27.8
Future Directions
• OMA guiding document for CORBA systems – falls short in average-size systems
• CORBA Component Model – abstracts system issues through programming constructs: • containers • subsystems
• CORBA working on architectural process – Model Driven Architecture™ (MDA)
• Expansion of OMG’s architecture – maintains compatibility with previous embodiments – gives new vitality to OMG 2002 Prentice Hall. All rights reserved.